summaryrefslogtreecommitdiffstats
path: root/vcl/backendtest
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /vcl/backendtest
parentInitial commit. (diff)
downloadlibreoffice-upstream/4%7.4.7.tar.xz
libreoffice-upstream/4%7.4.7.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--vcl/backendtest/GraphicsRenderTests.cxx2595
-rw-r--r--vcl/backendtest/VisualBackendTest.cxx886
-rw-r--r--vcl/backendtest/outputdevice/bitmap.cxx180
-rw-r--r--vcl/backendtest/outputdevice/clip.cxx82
-rw-r--r--vcl/backendtest/outputdevice/common.cxx1666
-rw-r--r--vcl/backendtest/outputdevice/gradient.cxx123
-rw-r--r--vcl/backendtest/outputdevice/line.cxx278
-rw-r--r--vcl/backendtest/outputdevice/outputdevice.cxx112
-rw-r--r--vcl/backendtest/outputdevice/pixel.cxx82
-rw-r--r--vcl/backendtest/outputdevice/polygon.cxx257
-rw-r--r--vcl/backendtest/outputdevice/polyline.cxx245
-rw-r--r--vcl/backendtest/outputdevice/polyline_b2d.cxx192
-rw-r--r--vcl/backendtest/outputdevice/polypolygon.cxx212
-rw-r--r--vcl/backendtest/outputdevice/polypolygon_b2d.cxx199
-rw-r--r--vcl/backendtest/outputdevice/rectangle.cxx142
-rw-r--r--vcl/backendtest/outputdevice/text.cxx34
16 files changed, 7285 insertions, 0 deletions
diff --git a/vcl/backendtest/GraphicsRenderTests.cxx b/vcl/backendtest/GraphicsRenderTests.cxx
new file mode 100644
index 000000000..962c60f94
--- /dev/null
+++ b/vcl/backendtest/GraphicsRenderTests.cxx
@@ -0,0 +1,2595 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+#include <svl/svlresid.hxx>
+#include <svl/svl.hrc>
+#include <unotools/bootstrap.hxx>
+#include <vcl/test/GraphicsRenderTests.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+
+#include <svdata.hxx>
+#include <salinst.hxx>
+#include <strings.hrc>
+#include <test/GraphicsRenderTests.hxx>
+
+#include <unordered_map>
+
+#define SHOULD_ASSERT \
+ (aOutDevTest.getRenderBackendName() != "qt5" && aOutDevTest.getRenderBackendName() != "qt5svp" \
+ && aOutDevTest.getRenderBackendName() != "gtk3svp" \
+ && aOutDevTest.getRenderBackendName() != "aqua" \
+ && aOutDevTest.getRenderBackendName() != "gen" \
+ && aOutDevTest.getRenderBackendName() != "genpsp" \
+ && aOutDevTest.getRenderBackendName() != "win")
+
+namespace vcl::test
+{
+static OUString activeGraphicsRenderTestName;
+void setActiveGraphicsRenderTest(const OUString& name) { activeGraphicsRenderTestName = name; }
+const OUString& activeGraphicsRenderTest() { return activeGraphicsRenderTestName; }
+} // namespace vcl::test
+
+OUString VclTestResult::getStatus(bool bLocalize)
+{ // tdf#145919 localize for UI but not in the log file
+ if (bLocalize)
+ {
+ if (m_aTestStatus == "PASSED")
+ {
+ return SvlResId(GRTSTR_PASSED);
+ }
+ else if (m_aTestStatus == "QUIRKY")
+ {
+ return SvlResId(GRTSTR_QUIRKY);
+ }
+ else if (m_aTestStatus == "FAILED")
+ {
+ return SvlResId(GRTSTR_FAILED);
+ }
+ else
+ {
+ return SvlResId(GRTSTR_SKIPPED);
+ }
+ }
+ else
+ return m_aTestStatus;
+}
+
+namespace
+{
+void exportBitmapExToImage(OUString const& rImageName, const BitmapEx& rBitmapEx)
+{
+ BitmapEx aBitmapEx(rBitmapEx);
+ aBitmapEx.Scale(Size(500, 500), BmpScaleFlag::Fast);
+ SvFileStream aStream(rImageName, StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmapEx, aStream);
+}
+bool is32bppSupported() { return ImplGetSVData()->mpDefInst->supportsBitmap32(); }
+
+// Some tests need special handling in drawing code (for example, not smoothscaling
+// when handling HiDPI bitmaps). Temporarily set up the test name to get such special
+// handling as well.
+class GraphicsTestZone
+{
+public:
+ GraphicsTestZone(std::u16string_view name)
+ {
+ vcl::test::setActiveGraphicsRenderTest(OUString::Concat("GraphicsRenderTest__") + name);
+ }
+ ~GraphicsTestZone() { vcl::test::setActiveGraphicsRenderTest(""); }
+};
+}
+
+OUString GraphicsRenderTests::returnTestStatus(vcl::test::TestResult const result)
+{
+ switch (result)
+ {
+ case vcl::test::TestResult::Passed:
+ return "PASSED";
+ case vcl::test::TestResult::PassedWithQuirks:
+ return "QUIRKY";
+ case vcl::test::TestResult::Failed:
+ return "FAILED";
+ }
+ return "SKIPPED";
+}
+
+void GraphicsRenderTests::testDrawRectWithRectangle()
+{
+ OUString aTestName = "testDrawRectWithRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ m_aCurGraphicsBackend = aOutDevTest.getRenderBackendName();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithPixel()
+{
+ OUString aTestName = "testDrawRectWithPixel";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithLine()
+{
+ OUString aTestName = "testDrawRectWithLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithPolygon()
+{
+ OUString aTestName = "testDrawRectWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithPolyLine()
+{
+ OUString aTestName = "testDrawRectWithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithPolyLineB2D()
+{
+ OUString aTestName = "testDrawRectWithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithPolyPolygon()
+{
+ OUString aTestName = "testDrawRectWithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectWithPolyPolygonB2D()
+{
+ OUString aTestName = "testDrawRectWithPolyPolygonB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithRectangle()
+{
+ OUString aTestName = "testDrawRectAAWithRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithPixel()
+{
+ OUString aTestName = "testDrawRectAAWithPixel";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithLine()
+{
+ OUString aTestName = "testDrawRectAAWithLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithPolygon()
+{
+ OUString aTestName = "testDrawRectAAWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithPolyLine()
+{
+ OUString aTestName = "testDrawRectAAWithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithPolyLineB2D()
+{
+ OUString aTestName = "testDrawRectAAWithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithPolyPolygon()
+{
+ OUString aTestName = "testDrawRectAAWithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectAAWithPolyPolygonB2D()
+{
+ OUString aTestName = "testDrawRectAAWithPolyPolygonB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangleAA(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawFilledRectWithRectangle()
+{
+ OUString aTestName = "testDrawFilledRectWithRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+ aTestName += "WithAA";
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawFilledRectWithPolygon()
+{
+ OUString aTestName = "testDrawFilledRectWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+ aTestName += "WithAA";
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawFilledRectWithPolyPolygon()
+{
+ OUString aTestName = "testDrawFilledRectWithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+ aTestName += "WithAA";
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawFilledRectWithPolyPolygon2D()
+{
+ OUString aTestName = "testDrawFilledRectWithPolyPolygon2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+ aTestName += "WithAA";
+ aBitmap = aOutDevTest.setupFilledRectangle(true);
+ eResult = vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDiamondWithPolygon()
+{
+ OUString aTestName = "testDrawDiamondWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDiamondWithLine()
+{
+ OUString aTestName = "testDrawDiamondWithLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDiamondWithPolyline()
+{
+ OUString aTestName = "testDrawDiamondWithPolyline";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDiamondWithPolylineB2D()
+{
+ OUString aTestName = "testDrawDiamondWithPolylineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawInvertWithRectangle()
+{
+ OUString aTestName = "testDrawInvertWithRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_NONE();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkInvertRectangle(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawInvertN50WithRectangle()
+{
+ OUString aTestName = "testDrawInvertN50WithRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_N50();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkInvertN50Rectangle(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawInvertTrackFrameWithRectangle()
+{
+ OUString aTestName = "testDrawInvertTrackFrameWithRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_TrackFrame();
+ if (!(SHOULD_ASSERT && aOutDevTest.getRenderBackendName() != "svp"))
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkInvertTrackFrameRectangle(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDropShapeWithPolyline()
+{
+ OUString aTestName = "testDrawDropShapeWithPolyline";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDropShape();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDropShapeAAWithPolyline()
+{
+ OUString aTestName = "testDrawDropShapeAAWithPolyline";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAADropShape();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBezierWithPolylineB2D()
+{
+ OUString aTestName = "testDrawBezierWithPolylineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupBezier();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkBezier(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBezierAAWithPolylineB2D()
+{
+ OUString aTestName = "testDrawBezierAAWithPolylineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAABezier();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkBezier(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDropShapeWithPolygon()
+{
+ OUString aTestName = "testDrawDropShapeWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDropShape();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawDropShapeAAWithPolygon()
+{
+ OUString aTestName = "testDrawDropShapeAAWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAADropShape();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestCommon::checkDropShape(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBitmap24bpp()
+{
+ OUString aTestName = "testDrawBitmap24bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N24_BPP);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawTransformedBitmap24bpp()
+{
+ OUString aTestName = "testDrawTransformedBitmap24bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N24_BPP);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testComplexDrawTransformedBitmap24bpp()
+{
+ OUString aTestName = "testComplexDrawTransformedBitmap24bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupComplexDrawTransformedBitmap(vcl::PixelFormat::N24_BPP);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkComplexTransformedBitmap(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBitmapExWithAlpha24bpp()
+{
+ OUString aTestName = "testDrawBitmapExWithAlpha24bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha(vcl::PixelFormat::N24_BPP);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawMask24bpp()
+{
+ OUString aTestName = "testDrawMask24bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawMask(vcl::PixelFormat::N24_BPP);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBlend24bpp()
+{
+ OUString aTestName = "testDrawBlend24bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ BitmapEx aBitmapEx = aOutDevTest.setupDrawBlend(vcl::PixelFormat::N24_BPP);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestBitmap::checkBlend(aBitmapEx);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmapEx.GetBitmap() : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawXor()
+{
+ OUString aTestName = "testDrawXor";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupXOR();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestAnotherOutDev::checkXOR(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testClipRectangle()
+{
+ OUString aTestName = "testClipRectangle";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipRectangle();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testClipPolygon()
+{
+ OUString aTestName = "testClipPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testClipPolyPolygon()
+{
+ OUString aTestName = "testClipPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipPolyPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testClipB2DPolyPolygon()
+{
+ OUString aTestName = "testClipB2DPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipB2DPolyPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOutDev()
+{
+ OUString aTestName = "testDrawOutDev";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDev();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDev(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOutDevScaledClipped()
+{
+ OUString aTestName = "testDrawOutDevScaledClipped";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDevScaledClipped();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDevScaledClipped(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOutDevSelf()
+{
+ OUString aTestName = "testDrawOutDevSelf";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDevSelf();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDevSelf(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDashedLine()
+{
+ OUString aTestName = "testDashedLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDashedLine();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkDashedLine(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLinearGradient()
+{
+ OUString aTestName = "testLinearGradient";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradient();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkLinearGradient(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLinearGradientAngled()
+{
+ OUString aTestName = "testLinearGradientAngled";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientAngled();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkLinearGradientAngled(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLinearGradientBorder()
+{
+ OUString aTestName = "testLinearGradientBorder";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientBorder();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkLinearGradientBorder(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLinearGradientIntensity()
+{
+ OUString aTestName = "testLinearGradientIntensity";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientIntensity();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkLinearGradientIntensity(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLinearGradientSteps()
+{
+ OUString aTestName = "testLinearGradientSteps";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientSteps();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkLinearGradientSteps(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testAxialGradient()
+{
+ OUString aTestName = "testAxialGradient";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAxialGradient();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkAxialGradient(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testRadialGradient()
+{
+ OUString aTestName = "testRadialGradient";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradient();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkRadialGradient(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testRadialGradientOfs()
+{
+ OUString aTestName = "testRadialGradientOfs";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradientOfs();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestGradient::checkRadialGradientOfs(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+}
+
+void GraphicsRenderTests::testLineJoinBevel()
+{
+ OUString aTestName = "testLineJoinBevel";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinBevel();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineJoinBevel(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLineJoinRound()
+{
+ OUString aTestName = "testLineJoinRound";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinRound();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineJoinRound(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLineJoinMiter()
+{
+ OUString aTestName = "testLineJoinMiter";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinMiter();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineJoinMiter(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLineJoinNone()
+{
+ OUString aTestName = "testLineJoinNone";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinNone();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineJoinNone(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLineCapRound()
+{
+ OUString aTestName = "testLineCapRound";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapRound();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineCapRound(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLineCapSquare()
+{
+ OUString aTestName = "testLineCapSquare";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapSquare();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineCapSquare(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testLineCapButt()
+{
+ OUString aTestName = "testLineCapButt";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapButt();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkLineCapButt(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testHalfEllipseWithPolyLine()
+{
+ OUString aTestName = "testHalfEllipseWithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkHalfEllipse(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testHalfEllipseAAWithPolyLine()
+{
+ OUString aTestName = "testHalfEllipseAAWithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkHalfEllipse(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testHalfEllipseWithPolyLineB2D()
+{
+ OUString aTestName = "testHalfEllipseWithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkHalfEllipse(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testHalfEllipseAAWithPolyLineB2D()
+{
+ OUString aTestName = "testHalfEllipseAAWithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkHalfEllipse(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testHalfEllipseWithPolygon()
+{
+ OUString aTestName = "testHalfEllipseWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkHalfEllipse(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testClosedBezierWithPolyline()
+{
+ OUString aTestName = "testClosedBezierWithPolyline";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClosedBezier();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkClosedBezier(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testClosedBezierWithPolygon()
+{
+ OUString aTestName = "testClosedBezierWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClosedBezier();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkClosedBezier(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testHalfEllipseAAWithPolygon()
+{
+ OUString aTestName = "testHalfEllipseAAWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupHalfEllipse(true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkHalfEllipse(aBitmap, true);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testFilledAsymmetricalDropShape()
+{
+ OUString aTestName = "testFilledAsymmetricalDropShape";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledAsymmetricalDropShape();
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkFilledAsymmetricalDropShape(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testTextDrawing()
+{
+ OUString aTestName = "testTextDrawing";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestText aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupTextBitmap();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestLine::checkTextLocation(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testEvenOddRuleInIntersectingRectsWithPolyPolygon()
+{
+ OUString aTestName = "testEvenOddRuleInIntersectingRectsWithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupIntersectingRectangles();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkEvenOddRuleInIntersectingRecs(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testEvenOddRuleInIntersectingRectsWithPolyPolygonB2D()
+{
+ OUString aTestName = "testEvenOddRuleInIntersectingRectsWithPolyPolygonB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupIntersectingRectangles();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestLine::checkEvenOddRuleInIntersectingRecs(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBitmap8bppGreyScale()
+{
+ OUString aTestName = "testDrawBitmap8bppGreyScale";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N8_BPP, true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap8bppGreyScale(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawTransformedBitmap8bppGreyScale()
+{
+ OUString aTestName = "testDrawTransformedBitmap8bppGreyScale";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N8_BPP, true);
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap8bppGreyScale(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBitmap32bpp()
+{
+ OUString aTestName = "testDrawBitmap32bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N32_BPP);
+ if (!SHOULD_ASSERT || !is32bppSupported())
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawTransformedBitmap32bpp()
+{
+ OUString aTestName = "testDrawTransformedBitmap32bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N32_BPP);
+ if (!SHOULD_ASSERT || !is32bppSupported())
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBitmapExWithAlpha32bpp()
+{
+ OUString aTestName = "testDrawBitmapExWithAlpha32bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha(vcl::PixelFormat::N32_BPP);
+ if (!SHOULD_ASSERT || !is32bppSupported())
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult
+ = vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawMask32bpp()
+{
+ OUString aTestName = "testDrawMask32bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawMask(vcl::PixelFormat::N32_BPP);
+ if (!SHOULD_ASSERT || !is32bppSupported())
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawBlend32bpp()
+{
+ OUString aTestName = "testDrawBlend32bpp";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ BitmapEx aBitmapEx = aOutDevTest.setupDrawBlend(vcl::PixelFormat::N32_BPP);
+ if (!SHOULD_ASSERT || !is32bppSupported())
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestBitmap::checkBlend(aBitmapEx);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmapEx.GetBitmap() : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithRect()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithRect";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ m_aCurGraphicsBackend = aOutDevTest.getRenderBackendName();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithRect()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithRect";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ m_aCurGraphicsBackend = aOutDevTest.getRenderBackendName();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithPixel()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithPixel";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithPixel()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithPixel";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithLine()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithLine()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithPolyLine()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithPolyLine()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithPolygon()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithPolygon()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithPolyLineB2D()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithPolyLineB2D()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithPolyPolygon()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithPolyPolygon()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize1028WithPolyPolygonB2D()
+{
+ OUString aTestName = "testDrawRectangleOnSize1028WithPolyPolygonB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize1028();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawRectangleOnSize4096WithPolygonPolygonB2D()
+{
+ OUString aTestName = "testDrawRectangleOnSize4096WithPolygonPolygonB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangleOnSize4096();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenPolygonWithPolyLine()
+{
+ OUString aTestName = "testDrawOpenPolygonWithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenPolygonWithPolyLineB2D()
+{
+ OUString aTestName = "testDrawOpenPolygonWithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenPolygonWithPolygon()
+{
+ OUString aTestName = "testDrawOpenPolygonWithPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenPolygonWithPolyPolygon()
+{
+ OUString aTestName = "testDrawOpenPolygonWithPolyPolygon";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenPolygonWithPolyPolygonB2D()
+{
+ OUString aTestName = "testDrawOpenPolygonWithPolyPolygonB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenPolygon();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenPolygon(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenBezierWithPolyLine()
+{
+ OUString aTestName = "testDrawOpenBezierWithPolyLine";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenBezier();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenBezier(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::testDrawOpenBezierWithPolyLineB2D()
+{
+ OUString aTestName = "testDrawOpenBezierWithPolyLineB2D";
+ GraphicsTestZone zone(aTestName);
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenBezier();
+ if (!SHOULD_ASSERT)
+ {
+ appendTestResult(aTestName, "SKIPPED");
+ return;
+ }
+ vcl::test::TestResult eResult = vcl::test::OutputDeviceTestCommon::checkOpenBezier(aBitmap);
+ appendTestResult(aTestName, returnTestStatus(eResult),
+ (m_aStoreResultantBitmap ? aBitmap : Bitmap()));
+ if (m_aStoreResultantBitmap)
+ {
+ BitmapEx aBitmapEx(aBitmap);
+ exportBitmapExToImage(m_aUserInstallPath + aTestName + ".png", aBitmapEx);
+ }
+}
+
+void GraphicsRenderTests::runALLTests()
+{
+ testDrawRectWithRectangle();
+ testDrawRectWithPixel();
+ testDrawRectWithLine();
+ testDrawRectWithPolygon();
+ testDrawRectWithPolyLine();
+ testDrawRectWithPolyLineB2D();
+ testDrawRectWithPolyPolygon();
+ testDrawRectWithPolyPolygonB2D();
+ testDrawRectAAWithRectangle();
+ testDrawRectAAWithPixel();
+ testDrawRectAAWithLine();
+ testDrawRectAAWithPolygon();
+ testDrawRectAAWithPolyLine();
+ testDrawRectAAWithPolyLineB2D();
+ testDrawRectAAWithPolyPolygon();
+ testDrawRectAAWithPolyPolygonB2D();
+ testDrawFilledRectWithRectangle();
+ testDrawFilledRectWithPolygon();
+ testDrawFilledRectWithPolyPolygon();
+ testDrawFilledRectWithPolyPolygon2D();
+ testDrawDiamondWithPolygon();
+ testDrawDiamondWithLine();
+ testDrawDiamondWithPolyline();
+ testDrawDiamondWithPolylineB2D();
+ testDrawInvertWithRectangle();
+ testDrawInvertN50WithRectangle();
+ testDrawInvertTrackFrameWithRectangle();
+ testDrawBezierWithPolylineB2D();
+ testDrawBezierAAWithPolylineB2D();
+ testDrawBitmap24bpp();
+ testDrawTransformedBitmap24bpp();
+ testComplexDrawTransformedBitmap24bpp();
+ testDrawBitmapExWithAlpha24bpp();
+ testDrawMask24bpp();
+ testDrawBlend24bpp();
+ testDrawXor();
+ testClipRectangle();
+ testClipPolygon();
+ testClipPolyPolygon();
+ testClipB2DPolyPolygon();
+ testDrawOutDev();
+ testDrawOutDevScaledClipped();
+ testDrawOutDevSelf();
+ testDashedLine();
+ testLinearGradient();
+ testLinearGradientAngled();
+ testLinearGradientBorder();
+ testLinearGradientIntensity();
+ testLinearGradientSteps();
+ testAxialGradient();
+ testRadialGradient();
+ testRadialGradientOfs();
+ testLineJoinBevel();
+ testLineJoinRound();
+ testLineJoinMiter();
+ testLineJoinNone();
+ testLineCapRound();
+ testLineCapSquare();
+ testLineCapButt();
+ testDrawDropShapeWithPolyline();
+ testDrawDropShapeAAWithPolyline();
+ testDrawDropShapeWithPolygon();
+ testDrawDropShapeAAWithPolygon();
+ testHalfEllipseWithPolyLine();
+ testHalfEllipseAAWithPolyLine();
+ testHalfEllipseWithPolyLineB2D();
+ testHalfEllipseAAWithPolyLineB2D();
+ testHalfEllipseWithPolygon();
+ testHalfEllipseAAWithPolygon();
+ testClosedBezierWithPolyline();
+ testClosedBezierWithPolygon();
+ testFilledAsymmetricalDropShape();
+ testTextDrawing();
+ testEvenOddRuleInIntersectingRectsWithPolyPolygon();
+ testEvenOddRuleInIntersectingRectsWithPolyPolygonB2D();
+ testDrawBitmap8bppGreyScale();
+ testDrawTransformedBitmap8bppGreyScale();
+ testDrawBitmap32bpp();
+ testDrawTransformedBitmap32bpp();
+ testDrawBitmapExWithAlpha32bpp();
+ testDrawMask32bpp();
+ testDrawBlend32bpp();
+ testDrawRectangleOnSize1028WithRect();
+ testDrawRectangleOnSize4096WithRect();
+ testDrawRectangleOnSize1028WithPixel();
+ testDrawRectangleOnSize4096WithPixel();
+ testDrawRectangleOnSize1028WithLine();
+ testDrawRectangleOnSize4096WithLine();
+ testDrawRectangleOnSize1028WithPolyLine();
+ testDrawRectangleOnSize4096WithPolyLine();
+ testDrawRectangleOnSize1028WithPolygon();
+ testDrawRectangleOnSize4096WithPolygon();
+ testDrawRectangleOnSize1028WithPolyLineB2D();
+ testDrawRectangleOnSize4096WithPolyLineB2D();
+ testDrawRectangleOnSize1028WithPolyPolygon();
+ testDrawRectangleOnSize4096WithPolyPolygon();
+ testDrawRectangleOnSize1028WithPolyPolygonB2D();
+ testDrawRectangleOnSize4096WithPolygonPolygonB2D();
+ testDrawOpenPolygonWithPolyLine();
+ testDrawOpenPolygonWithPolyLineB2D();
+ testDrawOpenPolygonWithPolygon();
+ testDrawOpenPolygonWithPolyPolygon();
+ testDrawOpenPolygonWithPolyPolygonB2D();
+ testDrawOpenBezierWithPolyLine();
+ testDrawOpenBezierWithPolyLineB2D();
+}
+
+void GraphicsRenderTests::appendTestResult(OUString aTestName, OUString aTestStatus,
+ Bitmap aTestBitmap)
+{
+ m_aTestResult.push_back(VclTestResult(aTestName, aTestStatus, aTestBitmap));
+}
+
+std::vector<VclTestResult>& GraphicsRenderTests::getTestResults() { return m_aTestResult; }
+
+OUString GraphicsRenderTests::getResultString(bool bLocalize)
+{
+ std::vector<int> testResults(4);
+ for (VclTestResult& test : m_aTestResult)
+ {
+ if (test.getStatus() == "PASSED")
+ {
+ testResults[0]++;
+ }
+ else if (test.getStatus() == "QUIRKY")
+ {
+ testResults[1]++;
+ }
+ else if (test.getStatus() == "FAILED")
+ {
+ testResults[2]++;
+ }
+ else
+ {
+ testResults[3]++;
+ }
+ }
+ // tdf#145919 localize for UI but not in the log file
+ OUString resultString;
+ if (bLocalize)
+ {
+ resultString
+ = VclResId(STR_GBU).replaceFirst("%1", m_aCurGraphicsBackend) + "\n"
+ + VclResId(STR_PASSED).replaceFirst("%1", OUString::number(testResults[0])) + "\n"
+ + VclResId(STR_QUIRKY).replaceFirst("%1", OUString::number(testResults[1])) + "\n"
+ + VclResId(STR_FAILED).replaceFirst("%1", OUString::number(testResults[2])) + "\n"
+ + VclResId(STR_SKIPPED).replaceFirst("%1", OUString::number(testResults[3])) + "\n";
+ }
+ else
+ {
+ resultString = "Graphics Backend used: " + m_aCurGraphicsBackend
+ + "\nPassed Tests: " + OUString::number(testResults[0])
+ + "\nQuirky Tests: " + OUString::number(testResults[1])
+ + "\nFailed Tests: " + OUString::number(testResults[2])
+ + "\nSkipped Tests: " + OUString::number(testResults[3]) + "\n";
+ }
+ return resultString;
+}
+
+void GraphicsRenderTests::run(bool storeResultBitmap)
+{
+ m_aStoreResultantBitmap = storeResultBitmap;
+ ::utl::Bootstrap::locateUserInstallation(m_aUserInstallPath);
+ if (storeResultBitmap)
+ {
+ m_aUserInstallPath += "/user/GraphicTestResults/";
+ }
+ else
+ {
+ m_aUserInstallPath += "/user/";
+ }
+ runALLTests();
+ //Storing the test's results in the main user installation directory.
+ SvFileStream logFile(m_aUserInstallPath + "GraphicsRenderTests.log",
+ StreamMode::WRITE | StreamMode::TRUNC);
+ std::unordered_map<OUString, std::vector<OUString>> aTests;
+ for (VclTestResult& tests : m_aTestResult)
+ {
+ aTests[tests.getStatus()].push_back(tests.getTestName());
+ }
+ OUString writeResult = getResultString() + "\n---Name of the tests that failed---\n";
+ if (static_cast<int>(aTests["FAILED"].size()) > 0)
+ {
+ for (const class OUString& tests : aTests["FAILED"])
+ {
+ writeResult += tests + "\n";
+ }
+ }
+ else
+ {
+ writeResult += "No test has been failed.\n";
+ }
+ writeResult += "\n---Name of the tests that were Quirky---\n";
+ if (static_cast<int>(aTests["QUIRKY"].size()) > 0)
+ {
+ for (const class OUString& tests : aTests["QUIRKY"])
+ {
+ writeResult += tests + "\n";
+ }
+ }
+ else
+ {
+ writeResult += "No test was Quirky.\n";
+ }
+ writeResult += "\n---Name of the tests that were Skipped---\n";
+ if (static_cast<int>(aTests["SKIPPED"].size()) > 0)
+ {
+ for (const class OUString& tests : aTests["SKIPPED"])
+ {
+ writeResult += tests + "\n";
+ }
+ }
+ else
+ {
+ writeResult += "No test was Skipped.";
+ }
+ logFile.WriteOString(OUStringToOString(writeResult, RTL_TEXTENCODING_UTF8));
+}
diff --git a/vcl/backendtest/VisualBackendTest.cxx b/vcl/backendtest/VisualBackendTest.cxx
new file mode 100644
index 000000000..f7da5e182
--- /dev/null
+++ b/vcl/backendtest/VisualBackendTest.cxx
@@ -0,0 +1,886 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <math.h>
+#include <sal/log.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <vcl/bitmapex.hxx>
+#include <vcl/event.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/vclmain.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/virdev.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <chrono>
+#include <iostream>
+
+#include <test/outputdevice.hxx>
+
+using namespace css;
+
+static void drawBitmapCentered(tools::Rectangle const& rRect, const Bitmap& aBitmap,
+ vcl::RenderContext& rRenderContext)
+{
+ tools::Long nWidth = rRect.GetWidth();
+ tools::Long nHeight = rRect.GetHeight();
+
+ Size aBitmapSize(aBitmap.GetSizePixel());
+
+ Point aPoint(rRect.TopLeft());
+
+ aPoint.AdjustX((nWidth - aBitmapSize.Width()) / 2 );
+ aPoint.AdjustY((nHeight - aBitmapSize.Height()) / 2 );
+
+ rRenderContext.DrawBitmap(aPoint, aBitmap);
+}
+
+static void drawBitmapScaledAndCentered(tools::Rectangle const & rRect, Bitmap aBitmap, vcl::RenderContext& rRenderContext, BmpScaleFlag aFlag = BmpScaleFlag::Fast)
+{
+ tools::Long nWidth = rRect.GetWidth();
+ tools::Long nHeight = rRect.GetHeight();
+
+ Size aBitmapSize(aBitmap.GetSizePixel());
+
+ double fWidthHeight = std::min(nWidth, nHeight);
+ double fScale = fWidthHeight / aBitmapSize.Width();
+ aBitmap.Scale(fScale, fScale, aFlag);
+
+ drawBitmapCentered(rRect, aBitmap, rRenderContext);
+}
+
+static void drawBackgroundRect(tools::Rectangle const & rRect, Color aColor, vcl::RenderContext& rRenderContext)
+{
+ rRenderContext.Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
+ rRenderContext.SetFillColor(aColor);
+ rRenderContext.SetLineColor(aColor);
+ rRenderContext.DrawRect(rRect);
+ rRenderContext.Pop();
+}
+
+static void assertAndSetBackground(vcl::test::TestResult eResult, tools::Rectangle const & rRect, vcl::RenderContext& rRenderContext)
+{
+ if (eResult == vcl::test::TestResult::Passed)
+ drawBackgroundRect(rRect, COL_GREEN, rRenderContext);
+ else if (eResult == vcl::test::TestResult::PassedWithQuirks)
+ drawBackgroundRect(rRect, COL_YELLOW, rRenderContext);
+ else if (eResult == vcl::test::TestResult::Failed)
+ drawBackgroundRect(rRect, COL_RED, rRenderContext);
+}
+
+namespace {
+
+class VisualBackendTestWindow : public WorkWindow
+{
+private:
+ Timer maUpdateTimer;
+ std::vector<std::chrono::high_resolution_clock::time_point> mTimePoints;
+ static constexpr unsigned char gnNumberOfTests = 12;
+ unsigned char mnTest;
+ bool mbAnimate;
+ ScopedVclPtr<VirtualDevice> mpVDev;
+
+public:
+ VisualBackendTestWindow()
+ : WorkWindow(nullptr, WB_APP | WB_STDWORK)
+ , maUpdateTimer("VisualBackendTestWindow maUpdateTimer")
+ , mnTest(10 * gnNumberOfTests)
+ , mbAnimate(mnTest % gnNumberOfTests == gnNumberOfTests - 1)
+ , mpVDev(VclPtr<VirtualDevice>::Create())
+ {
+ maUpdateTimer.SetInvokeHandler(LINK(this, VisualBackendTestWindow, updateHdl));
+ maUpdateTimer.SetPriority(TaskPriority::DEFAULT_IDLE);
+ if (mbAnimate)
+ {
+ maUpdateTimer.SetTimeout(1000.0);
+ maUpdateTimer.Start();
+ }
+ }
+
+ virtual ~VisualBackendTestWindow() override
+ {
+ disposeOnce();
+ }
+
+ DECL_LINK(updateHdl, Timer*, void);
+
+ virtual void KeyInput(const KeyEvent& rKEvt) override
+ {
+ sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
+
+ if (nCode == KEY_BACKSPACE)
+ mnTest--;
+ else if(nCode == KEY_SPACE)
+ mnTest++;
+
+ if (nCode != KEY_BACKSPACE && nCode != KEY_SPACE)
+ return;
+
+ if (mnTest % gnNumberOfTests == gnNumberOfTests - 1)
+ {
+ mbAnimate = true;
+ maUpdateTimer.Start();
+ }
+ else
+ {
+ mbAnimate = false;
+ Invalidate();
+ }
+ }
+
+ static std::vector<tools::Rectangle> setupRegions(int nPartitionsX, int nPartitionsY, int nWidth, int nHeight)
+ {
+ std::vector<tools::Rectangle> aRegions;
+
+ for (int y = 0; y < nPartitionsY; y++)
+ {
+ for (int x = 0; x < nPartitionsX; x++)
+ {
+ tools::Long x1 = x * (nWidth / nPartitionsX);
+ tools::Long y1 = y * (nHeight / nPartitionsY);
+ tools::Long x2 = (x+1) * (nWidth / nPartitionsX);
+ tools::Long y2 = (y+1) * (nHeight / nPartitionsY);
+
+ aRegions.emplace_back(x1 + 1, y1 + 1, x2 - 6, y2 - 2);
+ }
+ }
+ return aRegions;
+ }
+
+ static void testRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight, bool AA)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(4, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle(AA);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangles(aBitmap, AA), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testFilledRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(4, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygonB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true);
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testDiamondsAndBezier(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupOpenBezier();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkOpenBezier(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLineB2D aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAABezier();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkBezier(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testLines(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLines();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLines();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLines();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAALines();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAALines();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAALines();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testLineTypes(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(4, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinBevel();
+ assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkLineJoinBevel(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinRound();
+ assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkLineJoinRound(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinMiter();
+ assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkLineJoinMiter(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineJoinNone();
+ assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkLineJoinNone(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapRound();
+ assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkLineCapRound(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapSquare();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLineCapSquare(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLineCapButt();
+ assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLineCapButt(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testBitmaps(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap(vcl::PixelFormat::N24_BPP);
+ assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(vcl::PixelFormat::N24_BPP);
+ assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupComplexDrawTransformedBitmap(vcl::PixelFormat::N24_BPP);
+ assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkComplexTransformedBitmap(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha(vcl::PixelFormat::N24_BPP);
+ assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawMask(vcl::PixelFormat::N24_BPP);
+ assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ BitmapEx aBitmap = aOutDevTest.setupDrawBlend(vcl::PixelFormat::N24_BPP);
+ assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkBlend(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap.GetBitmap(), rRenderContext);
+ }
+ }
+
+ static void testInvert(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_NONE();
+ assertAndSetBackground(vcl::test::OutputDeviceTestRect::checkInvertRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_N50();
+ assertAndSetBackground(vcl::test::OutputDeviceTestRect::checkInvertN50Rectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupInvert_TrackFrame();
+ assertAndSetBackground(vcl::test::OutputDeviceTestRect::checkInvertTrackFrameRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupXOR();
+ assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkXOR(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testClip(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipRectangle();
+ assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipPolygon();
+ assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipPolyPolygon();
+ assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestClip aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupClipB2DPolyPolygon();
+ assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ static void testGradients(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ tools::Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<tools::Rectangle> aRegions = setupRegions(4, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradient();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkLinearGradient(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientAngled();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkLinearGradientAngled(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientBorder();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkLinearGradientBorder(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientIntensity();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkLinearGradientIntensity(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradientSteps();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkLinearGradientSteps(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAxialGradient();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkAxialGradient(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradient();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkRadialGradient(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradientOfs();
+ assertAndSetBackground(vcl::test::OutputDeviceTestGradient::checkRadialGradientOfs(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) override
+ {
+ if (mnTest % gnNumberOfTests == gnNumberOfTests - 1)
+ {
+ rRenderContext.SetBackground(Wallpaper(COL_GREEN));
+
+ static size_t nTimeIndex = 0;
+ static const size_t constSamplesFPS = 120;
+ double fps = 0.0;
+
+ if (mTimePoints.size() < constSamplesFPS)
+ {
+ mTimePoints.push_back(std::chrono::high_resolution_clock::now());
+ nTimeIndex++;
+ }
+ else
+ {
+ size_t current = nTimeIndex % constSamplesFPS;
+ mTimePoints[current] = std::chrono::high_resolution_clock::now();
+ size_t last = (nTimeIndex + 1) % constSamplesFPS;
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(mTimePoints[current] - mTimePoints[last]).count();
+ fps = constSamplesFPS * 1000.0 / ms;
+ nTimeIndex++;
+ }
+
+ double fTime = 0.5 + std::sin(nTimeIndex / 100.0) / 2.0;
+
+ Size aSizePixel = GetSizePixel();
+
+ mpVDev->SetAntialiasing(AntialiasingFlags::Enable | AntialiasingFlags::PixelSnapHairline);
+ mpVDev->SetOutputSizePixel(aSizePixel);
+ mpVDev->SetBackground(Wallpaper(COL_LIGHTGRAY));
+ mpVDev->Erase();
+ mpVDev->SetFillColor(COL_LIGHTRED);
+ mpVDev->SetLineColor(COL_LIGHTBLUE);
+
+ basegfx::B2DPolyPolygon polyPolygon;
+
+ for (int b=10; b<14; b++)
+ {
+ basegfx::B2DPolygon polygon;
+ for (double a=0.0; a<360.0; a+=0.5)
+ {
+ double x = std::sin(basegfx::deg2rad(a)) * (b+1) * 20;
+ double y = std::cos(basegfx::deg2rad(a)) * (b+1) * 20;
+ polygon.append(basegfx::B2DPoint(x + 200 + 500 * fTime, y + 200 + 500 * fTime));
+ }
+ polygon.setClosed(true);
+ polyPolygon.append(polygon);
+ }
+
+ mpVDev->DrawPolyPolygon(polyPolygon);
+
+ tools::Rectangle aGradientRect(Point(200, 200), Size(200 + fTime * 300, 200 + fTime * 300));
+ mpVDev->DrawGradient(aGradientRect, Gradient(GradientStyle::Linear, COL_YELLOW, COL_BLUE));
+
+ rRenderContext.DrawOutDev(Point(), mpVDev->GetOutputSizePixel(),
+ Point(), mpVDev->GetOutputSizePixel(),
+ *mpVDev);
+ rRenderContext.SetTextColor(COL_LIGHTRED);
+ rRenderContext.DrawText(Point(10, 10), "FPS: " + OUString::number(int(fps)));
+ return;
+ }
+
+ rRenderContext.SetBackground(Wallpaper(COL_GREEN));
+
+ Size aSize = GetOutputSizePixel();
+
+ tools::Long nWidth = aSize.Width();
+ tools::Long nHeight = aSize.Height();
+
+ if (mnTest % gnNumberOfTests == 0)
+ {
+ testRectangles(rRenderContext, nWidth, nHeight, false);
+ }
+ else if (mnTest % gnNumberOfTests == 1)
+ {
+ testRectangles(rRenderContext, nWidth, nHeight, true);
+ }
+ else if (mnTest % gnNumberOfTests == 2)
+ {
+ testFilledRectangles(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 3)
+ {
+ testDiamondsAndBezier(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 4)
+ {
+ testLines(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 5)
+ {
+ testLineTypes(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 6)
+ {
+ testBitmaps(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 7)
+ {
+ testInvert(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 8)
+ {
+ testClip(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 9)
+ {
+ testGradients(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % gnNumberOfTests == 10)
+ {
+ std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight);
+ size_t index = 0;
+
+ tools::Rectangle aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDev();
+ assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDev(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDevScaledClipped();
+ assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDevScaledClipped(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDevSelf();
+ assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDevSelf(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDashedLine();
+ assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkDashedLine(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+ }
+};
+
+}
+
+IMPL_LINK_NOARG(VisualBackendTestWindow, updateHdl, Timer *, void)
+{
+ if (mbAnimate)
+ {
+ maUpdateTimer.SetTimeout(1.0);
+ maUpdateTimer.Start();
+ Invalidate();
+ }
+}
+
+namespace {
+
+class VisualBackendTestApp : public Application
+{
+
+public:
+ VisualBackendTestApp()
+ {}
+
+ virtual int Main() override
+ {
+ try
+ {
+ ScopedVclPtrInstance<VisualBackendTestWindow> aMainWindow;
+
+ aMainWindow->SetText("VCL Test");
+ aMainWindow->Show();
+
+ Application::Execute();
+ }
+ catch (const css::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("vcl.app", "Fatal");
+ return 1;
+ }
+ catch (const std::exception& rException)
+ {
+ SAL_WARN("vcl.app", "Fatal exception: " << rException.what());
+ return 1;
+ }
+ return 0;
+ }
+
+protected:
+ void Init() override
+ {
+ try
+ {
+ uno::Reference<uno::XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext();
+ uno::Reference<lang::XMultiServiceFactory> xMSF(xComponentContext->getServiceManager(), uno::UNO_QUERY);
+
+ if (!xMSF.is())
+ Application::Abort("Bootstrap failure - no service manager");
+
+ comphelper::setProcessServiceFactory(xMSF);
+ }
+ catch (const uno::Exception &e)
+ {
+ Application::Abort("Bootstrap exception " + e.Message);
+ }
+ }
+
+ void DeInit() override
+ {
+ comphelper::setProcessServiceFactory(nullptr);
+ }
+};
+
+}
+
+void vclmain::createApplication()
+{
+ static VisualBackendTestApp aApplication;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/bitmap.cxx b/vcl/backendtest/outputdevice/bitmap.cxx
new file mode 100644
index 000000000..5b491badf
--- /dev/null
+++ b/vcl/backendtest/outputdevice/bitmap.cxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+#include <vcl/bitmapex.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+
+namespace vcl::test {
+
+Bitmap OutputDeviceTestBitmap::setupDrawTransformedBitmap(vcl::PixelFormat aBitmapFormat,bool isBitmapGreyScale)
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, aBitmapFormat);
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(constFillColor);
+ aWriteAccess->SetLineColor(COL_YELLOW);
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(2, 2, 6, 6));
+ }
+
+ if (isBitmapGreyScale)
+ aBitmap.Convert(BmpConversion::N8BitGreys);
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ basegfx::B2DHomMatrix aTransform;
+ aTransform.scale(aBitmapSize.Width(), aBitmapSize.Height());
+ aTransform.translate((maVDRectangle.GetWidth() / 2.0) - (aBitmapSize.Width() / 2.0),
+ (maVDRectangle.GetHeight() / 2.0) - (aBitmapSize.Height() / 2.0));
+
+ mpVirtualDevice->DrawTransformedBitmapEx(aTransform, BitmapEx(aBitmap));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+
+Bitmap OutputDeviceTestBitmap::setupComplexDrawTransformedBitmap(vcl::PixelFormat aBitmapFormat,bool isBitmapGreyScale)
+{
+ Size aBitmapSize(6, 6);
+ Bitmap aBitmap(aBitmapSize, aBitmapFormat);
+ aBitmap.Erase(constFillColor);
+
+ if (isBitmapGreyScale)
+ aBitmap.Convert(BmpConversion::N8BitGreys);
+
+ initialSetup(17, 14, constBackgroundColor);
+
+ basegfx::B2DHomMatrix aTransform;
+ aTransform.shearX(0.25);
+ aTransform.scale(aBitmapSize.Width() * 2, aBitmapSize.Height() * 2);
+ aTransform.translate(1, 1);
+
+ mpVirtualDevice->DrawTransformedBitmapEx(aTransform, BitmapEx(aBitmap));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+
+Bitmap OutputDeviceTestBitmap::setupDrawBitmap(vcl::PixelFormat aBitmapFormat,bool isBitmapGreyScale)
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, aBitmapFormat);
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(constFillColor);
+ aWriteAccess->SetLineColor(COL_YELLOW);
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(2, 2, 6, 6));
+ }
+
+ if (isBitmapGreyScale)
+ aBitmap.Convert(BmpConversion::N8BitGreys);
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ Point aPoint((maVDRectangle.GetWidth() / 2.0) - (aBitmapSize.Width() / 2.0),
+ (maVDRectangle.GetHeight() / 2.0) - (aBitmapSize.Height() / 2.0));
+
+ mpVirtualDevice->DrawBitmapEx(aPoint, BitmapEx(aBitmap));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestBitmap::setupDrawBitmapExWithAlpha(vcl::PixelFormat aBitmapFormat)
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, aBitmapFormat);
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(Color(0xFF, 0xFF, 0x00));
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
+ }
+
+ AlphaMask aAlpha(aBitmapSize);
+ {
+ AlphaScopedWriteAccess aWriteAccess(aAlpha);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44));
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
+ }
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ Point aPoint(alignToCenter(maVDRectangle, tools::Rectangle(Point(), aBitmapSize)).TopLeft());
+
+ mpVirtualDevice->DrawBitmapEx(aPoint, BitmapEx(aBitmap, aAlpha));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestBitmap::setupDrawMask(vcl::PixelFormat aBitmapFormat)
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, aBitmapFormat);
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(COL_BLACK);
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
+ }
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->DrawMask(Point(2, 2), aBitmap, constLineColor);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+BitmapEx OutputDeviceTestBitmap::setupDrawBlend(vcl::PixelFormat aBitmapFormat)
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, aBitmapFormat);
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(Color(0xFF, 0xFF, 0x00));
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
+ }
+
+ AlphaMask aAlpha(aBitmapSize);
+ {
+ AlphaScopedWriteAccess aWriteAccess(aAlpha);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44));
+ aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5));
+ }
+
+ initialSetup(13, 13, COL_TRANSPARENT, false, true);
+ mpVirtualDevice->SetFillColor(constBackgroundColor);
+ mpVirtualDevice->SetLineColor(constBackgroundColor);
+ // Leave the outer part of the device transparent, the inner part set to the background color.
+ // This will test blending of VirtualDevice's "alpha" device (outer yellow rectangle
+ // will be blended with transparent background, inner with the grey one).
+ mpVirtualDevice->DrawRect( tools::Rectangle( Point( 3, 3 ), Size( 7, 7 )));
+
+ Point aPoint(alignToCenter(maVDRectangle, tools::Rectangle(Point(), aBitmapSize)).TopLeft());
+
+ mpVirtualDevice->DrawBitmapEx(aPoint, BitmapEx(aBitmap, aAlpha));
+
+ return mpVirtualDevice->GetBitmapEx(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/clip.cxx b/vcl/backendtest/outputdevice/clip.cxx
new file mode 100644
index 000000000..495b43b6f
--- /dev/null
+++ b/vcl/backendtest/outputdevice/clip.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+Bitmap OutputDeviceTestClip::setupClipRectangle()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(2);
+ mpVirtualDevice->SetClipRegion(vcl::Region(rectangle));
+ mpVirtualDevice->SetBackground(constFillColor);
+ mpVirtualDevice->Erase(maVDRectangle);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestClip::setupClipPolygon()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(2);
+ mpVirtualDevice->SetClipRegion(vcl::Region(tools::Polygon(rectangle)));
+ mpVirtualDevice->SetBackground(constFillColor);
+ mpVirtualDevice->Erase(maVDRectangle);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestClip::setupClipPolyPolygon()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(2);
+ mpVirtualDevice->SetClipRegion(vcl::Region(tools::PolyPolygon(rectangle)));
+ mpVirtualDevice->SetBackground(constFillColor);
+ mpVirtualDevice->Erase(maVDRectangle);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestClip::setupClipB2DPolyPolygon()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(2);
+ mpVirtualDevice->SetClipRegion(vcl::Region(basegfx::B2DPolyPolygon(basegfx::B2DPolygon{
+ basegfx::B2DPoint(rectangle.Left(), rectangle.Top()),
+ basegfx::B2DPoint(rectangle.Left(), rectangle.Bottom()),
+ basegfx::B2DPoint(rectangle.Right(), rectangle.Bottom()),
+ basegfx::B2DPoint(rectangle.Right(), rectangle.Top()),
+ })));
+ mpVirtualDevice->SetBackground(constFillColor);
+ mpVirtualDevice->Erase(maVDRectangle);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+TestResult OutputDeviceTestClip::checkClip(Bitmap& aBitmap)
+{
+ std::vector<Color> aExpected{ constBackgroundColor, constBackgroundColor, constFillColor,
+ constFillColor, constFillColor, constFillColor,
+ constFillColor };
+ return checkRectangles(aBitmap, aExpected);
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/common.cxx b/vcl/backendtest/outputdevice/common.cxx
new file mode 100644
index 000000000..adbae9599
--- /dev/null
+++ b/vcl/backendtest/outputdevice/common.cxx
@@ -0,0 +1,1666 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <salgdi.hxx>
+
+namespace vcl::test {
+
+namespace
+{
+
+
+int deltaColor(BitmapColor aColor1, BitmapColor aColor2)
+{
+ int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed());
+ int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen());
+ int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue());
+
+ return std::max(std::max(deltaR, deltaG), deltaB);
+}
+
+void checkValue(BitmapScopedWriteAccess& pAccess, int x, int y, Color aExpected,
+ int& nNumberOfQuirks, int& nNumberOfErrors, bool bQuirkMode, int nColorDeltaThresh = 0)
+{
+ const bool bColorize = false;
+ Color aColor = pAccess->GetPixel(y, x);
+ int nColorDelta = deltaColor(aColor, aExpected);
+
+ if (nColorDelta <= nColorDeltaThresh)
+ {
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTGREEN);
+ }
+ else if (bQuirkMode)
+ {
+ nNumberOfQuirks++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_YELLOW);
+ }
+ else
+ {
+ nNumberOfErrors++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTRED);
+ }
+}
+
+void checkValue(BitmapScopedWriteAccess& pAccess, const Point& point, Color aExpected,
+ int& nNumberOfQuirks, int& nNumberOfErrors, bool bQuirkMode, int nColorDeltaThresh = 0)
+{
+ checkValue(pAccess, point.getX(), point.getY(), aExpected, nNumberOfQuirks, nNumberOfErrors, bQuirkMode, nColorDeltaThresh);
+}
+
+void checkValue(BitmapScopedWriteAccess& pAccess, int x, int y, Color aExpected,
+ int& nNumberOfQuirks, int& nNumberOfErrors, int nColorDeltaThresh, int nColorDeltaThreshQuirk = 0)
+{
+ const bool bColorize = false;
+ Color aColor = pAccess->GetPixel(y, x);
+ int nColorDelta = deltaColor(aColor, aExpected);
+ nColorDeltaThreshQuirk = std::max( nColorDeltaThresh, nColorDeltaThreshQuirk);
+
+ if (nColorDelta <= nColorDeltaThresh)
+ {
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTGREEN);
+ }
+ else if (nColorDelta <= nColorDeltaThreshQuirk)
+ {
+ nNumberOfQuirks++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_YELLOW);
+ }
+ else
+ {
+ nNumberOfErrors++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTRED);
+ }
+}
+
+char returnDominantColor(Color aColor)
+{
+ int aRed = aColor.GetRed();
+ int aGreen = aColor.GetGreen();
+ int aBlue = aColor.GetBlue();
+ if (aRed > aGreen && aRed > aBlue)
+ return 'R';
+
+ if (aGreen > aRed && aGreen > aBlue)
+ return 'G';
+
+ if(aBlue > aRed && aBlue > aGreen)
+ return 'B';
+
+ return 'X'; //No Dominant Color.
+}
+
+void checkValueAA(BitmapScopedWriteAccess& pAccess, int x, int y, Color aExpected,
+ int& nNumberOfQuirks, int& nNumberOfErrors, int nColorDeltaThresh = 64)
+{
+ const bool bColorize = false;
+ Color aColor = pAccess->GetPixel(y, x);
+ bool aColorResult = returnDominantColor(aExpected) == returnDominantColor(aColor);
+ int nColorDelta = deltaColor(aColor, aExpected);
+
+ if (nColorDelta <= nColorDeltaThresh && aColorResult)
+ {
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTGREEN);
+ }
+ else if (aColorResult)
+ {
+ nNumberOfQuirks++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_YELLOW);
+ }
+ else
+ {
+ nNumberOfErrors++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTRED);
+ }
+}
+
+// Return all colors in the rectangle and their count.
+std::map<Color, int> collectColors(Bitmap& bitmap, const tools::Rectangle& rectangle)
+{
+ std::map<Color, int> colors;
+ BitmapScopedWriteAccess pAccess(bitmap);
+ for (tools::Long y = rectangle.Top(); y < rectangle.Bottom(); ++y)
+ for (tools::Long x = rectangle.Left(); x < rectangle.Right(); ++x)
+ ++colors[pAccess->GetPixel(y, x)]; // operator[] initializes to 0 (default ctor) if creating
+ return colors;
+}
+
+bool checkConvexHullProperty(Bitmap& bitmap, Color constLineColor, int nWidthOffset,
+ int nHeightOffset)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ tools::Long thresholdWidth = pAccess->Width() - nWidthOffset;
+ tools::Long thresholdHeight = pAccess->Height() - nHeightOffset;
+ for (tools::Long y = 0; y < pAccess->Height(); ++y)
+ {
+ for (tools::Long x = 0; x < pAccess->Width(); ++x)
+ {
+ /*
+ If the shape exceeds the threshold limit of height or width or both,
+ this would indicate that the bezier curve is not within its convex polygon and
+ hence is faulty.
+ */
+ if (pAccess->GetPixel(y, x) == constLineColor
+ && (thresholdHeight < y || thresholdWidth < x))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+TestResult checkRect(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+ tools::Long nHeight = pAccess->Height();
+ tools::Long nWidth = pAccess->Width();
+
+ tools::Long firstX = 0 + aLayerNumber;
+ tools::Long firstY = 0 + aLayerNumber;
+
+ tools::Long lastX = nWidth - aLayerNumber - 1;
+ tools::Long lastY = nHeight - aLayerNumber - 1;
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // check corner quirks
+ checkValue(pAccess, firstX, firstY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, lastX, firstY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, firstX, lastY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, lastX, lastY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+
+ for (tools::Long y = firstY + 1; y <= lastY - 1; y++)
+ {
+ checkValue(pAccess, firstX, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(pAccess, lastX, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ }
+ for (tools::Long x = firstX + 1; x <= lastX - 1; x++)
+ {
+ checkValue(pAccess, x, firstY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(pAccess, x, lastY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ }
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult checkHorizontalVerticalDiagonalLines(Bitmap& rBitmap, Color aExpectedColor, int nColorThresh)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+ tools::Long nWidth = pAccess->Width();
+ tools::Long nHeight = pAccess->Height();
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // check horizontal line
+ {
+ tools::Long startX = 4;
+ tools::Long endX = nWidth - 2;
+
+ tools::Long y = 1;
+
+ checkValue(pAccess, startX, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+ checkValue(pAccess, endX, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+
+ for (tools::Long x = startX + 1; x <= endX - 1; x++)
+ {
+ checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false, nColorThresh);
+ }
+ }
+
+ // check vertical line
+ {
+ tools::Long startY = 4;
+ tools::Long endY = nHeight - 2;
+
+ tools::Long x = 1;
+
+ checkValue(pAccess, x, startY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+ checkValue(pAccess, x, endY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+
+ for (tools::Long y = startY + 1; y <= endY - 1; y++)
+ {
+ checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false, nColorThresh);
+ }
+ }
+
+ // check diagonal line
+ {
+ tools::Long startX = 1;
+ tools::Long endX = nWidth - 2;
+
+ tools::Long startY = 1;
+ tools::Long endY = nHeight - 2;
+
+ tools::Long x = startX;
+ tools::Long y = startY;
+
+ checkValue(pAccess, startX, startY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+ checkValue(pAccess, endX, endY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+
+ x++; y++;
+
+ while(y <= endY - 1 && x <= endX - 1)
+ {
+ checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false, nColorThresh);
+ x++; y++;
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult checkDiamondLine(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+ tools::Long nHeight = pAccess->Height();
+ tools::Long nWidth = pAccess->Width();
+
+ tools::Long midX = nWidth / 2;
+ tools::Long midY = nHeight / 2;
+
+ tools::Long firstX = aLayerNumber;
+ tools::Long lastX = nWidth - aLayerNumber - 1;
+
+ tools::Long firstY = aLayerNumber;
+ tools::Long lastY = nHeight - aLayerNumber - 1;
+
+ tools::Long offsetFromMid = 0;
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ checkValue(pAccess, firstX, midY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, lastX, midY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, midX, firstY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, midX, lastY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true);
+
+ offsetFromMid = 1;
+ for (tools::Long x = firstX + 1; x <= midX - 1; x++)
+ {
+ checkValue(pAccess, x, midY - offsetFromMid, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(pAccess, x, midY + offsetFromMid, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+
+ offsetFromMid++;
+ }
+
+ offsetFromMid = midY - aLayerNumber - 1;
+
+ for (tools::Long x = midX + 1; x <= lastX - 1; x++)
+ {
+ checkValue(pAccess, x, midY - offsetFromMid, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(pAccess, x, midY + offsetFromMid, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+
+ offsetFromMid--;
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+} // end anonymous namespace
+
+const Color OutputDeviceTestCommon::constBackgroundColor(COL_LIGHTGRAY);
+const Color OutputDeviceTestCommon::constLineColor(COL_LIGHTBLUE);
+const Color OutputDeviceTestCommon::constFillColor(COL_BLUE);
+
+OutputDeviceTestCommon::OutputDeviceTestCommon()
+{}
+
+OUString OutputDeviceTestCommon::getRenderBackendName() const
+{
+ if (mpVirtualDevice && mpVirtualDevice->GetGraphics())
+ {
+ SalGraphics const * pGraphics = mpVirtualDevice->GetGraphics();
+ return pGraphics->getRenderBackendName();
+ }
+ return OUString();
+}
+
+void OutputDeviceTestCommon::initialSetup(tools::Long nWidth, tools::Long nHeight, Color aColor, bool bEnableAA, bool bAlphaVirtualDevice)
+{
+ if (bAlphaVirtualDevice)
+ mpVirtualDevice = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+ else
+ mpVirtualDevice = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
+
+ maVDRectangle = tools::Rectangle(Point(), Size (nWidth, nHeight));
+ mpVirtualDevice->SetOutputSizePixel(maVDRectangle.GetSize());
+ if (bEnableAA)
+ mpVirtualDevice->SetAntialiasing(AntialiasingFlags::Enable | AntialiasingFlags::PixelSnapHairline);
+ else
+ mpVirtualDevice->SetAntialiasing(AntialiasingFlags::NONE);
+ mpVirtualDevice->SetBackground(Wallpaper(aColor));
+ mpVirtualDevice->Erase();
+}
+
+TestResult OutputDeviceTestCommon::checkLines(Bitmap& rBitmap)
+{
+ return checkHorizontalVerticalDiagonalLines(rBitmap, constLineColor, 0);
+}
+
+TestResult OutputDeviceTestCommon::checkAALines(Bitmap& rBitmap)
+{
+ return checkHorizontalVerticalDiagonalLines(rBitmap, constLineColor, 30); // 30 color values threshold delta
+}
+
+static void checkResult(TestResult eResult, TestResult & eTotal)
+{
+ if (eTotal == TestResult::Failed)
+ return;
+
+ if (eResult == TestResult::Failed)
+ eTotal = TestResult::Failed;
+
+ if (eResult == TestResult::PassedWithQuirks)
+ eTotal = TestResult::PassedWithQuirks;
+}
+
+TestResult OutputDeviceTestCommon::checkInvertRectangle(Bitmap& aBitmap)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ TestResult eResult;
+
+ std::vector<Color> aExpected{ COL_WHITE, COL_WHITE };
+ eResult = checkRectangles(aBitmap, aExpected);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkFilled(aBitmap, tools::Rectangle(Point(2, 2), Size(8, 8)), COL_LIGHTCYAN);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkFilled(aBitmap, tools::Rectangle(Point(10, 2), Size(8, 8)), COL_LIGHTMAGENTA);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkFilled(aBitmap, tools::Rectangle(Point(2, 10), Size(8, 8)), COL_YELLOW);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkFilled(aBitmap, tools::Rectangle(Point(10, 10), Size(8, 8)), COL_BLACK);
+ checkResult(eResult, aReturnValue);
+
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestCommon::checkChecker(Bitmap& rBitmap, sal_Int32 nStartX, sal_Int32 nEndX, sal_Int32 nStartY, sal_Int32 nEndY, std::vector<Color> const & rExpected)
+{
+ TestResult aReturnValue = TestResult::Passed;
+
+ int choice = 0;
+ for (sal_Int32 y = nStartY; y <= nEndY; ++y)
+ {
+ for (sal_Int32 x = nStartX; x <= nEndX; ++x)
+ {
+ TestResult eResult = checkFilled(rBitmap, tools::Rectangle(Point(x, y), Size(1, 1)), rExpected[choice % 2]);
+ checkResult(eResult, aReturnValue);
+ choice++;
+ }
+ choice++;
+ }
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestCommon::checkInvertN50Rectangle(Bitmap& aBitmap)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ TestResult eResult;
+
+ std::vector<Color> aExpected{ COL_WHITE, COL_WHITE };
+ eResult = checkRectangles(aBitmap, aExpected);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkChecker(aBitmap, 2, 9, 2, 9, { COL_LIGHTCYAN, COL_LIGHTRED });
+ checkResult(eResult, aReturnValue);
+ eResult = checkChecker(aBitmap, 2, 9, 10, 17, { COL_YELLOW, COL_LIGHTBLUE });
+ checkResult(eResult, aReturnValue);
+ eResult = checkChecker(aBitmap, 10, 17, 2, 9, { COL_LIGHTMAGENTA, COL_LIGHTGREEN });
+ checkResult(eResult, aReturnValue);
+ eResult = checkChecker(aBitmap, 10, 17, 10, 17, { COL_BLACK, COL_WHITE });
+ checkResult(eResult, aReturnValue);
+
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestCommon::checkInvertTrackFrameRectangle(Bitmap& aBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ COL_WHITE, COL_WHITE
+ };
+ return checkRectangles(aBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestCommon::checkRectangle(Bitmap& aBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor, constLineColor,
+ constBackgroundColor, constBackgroundColor, constLineColor, constBackgroundColor
+ };
+ return checkRectangles(aBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestCommon::checkRectangles(Bitmap& rBitmap, bool aEnableAA)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ std::vector<Color> aExpected = { constBackgroundColor, constLineColor, constLineColor };
+
+ for (size_t aLayerNumber = 0; aLayerNumber < aExpected.size(); aLayerNumber++)
+ {
+ tools::Long startX = aLayerNumber, endX = pAccess->Width() / 2 - aLayerNumber + 1;
+ tools::Long startY = aLayerNumber, endY = pAccess->Height() - aLayerNumber - 1;
+
+ for (tools::Long ptX = startX; ptX <= endX; ++ptX)
+ {
+ if (aEnableAA)
+ {
+ checkValueAA(pAccess, ptX, startY + (aLayerNumber == 2 ? 2 : 0),
+ aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors);
+ checkValueAA(pAccess, ptX, endY - (aLayerNumber == 2 ? 2 : 0),
+ aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors);
+ }
+ else
+ {
+ checkValue(pAccess, ptX, startY + (aLayerNumber == 2 ? 2 : 0),
+ aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors, true);
+ checkValue(pAccess, ptX, endY - (aLayerNumber == 2 ? 2 : 0),
+ aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ }
+ for (tools::Long ptY = startY + (aLayerNumber == 2 ? 2 : 0);
+ ptY <= endY - (aLayerNumber == 2 ? 2 : 0); ++ptY)
+ {
+ if (aEnableAA)
+ {
+ checkValueAA(pAccess, startX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors);
+ checkValueAA(pAccess, endX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors);
+ }
+ else
+ {
+ checkValue(pAccess, startX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors, true);
+ checkValue(pAccess, endX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors, true);
+ }
+ }
+ }
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkRectangleAA(Bitmap& aBitmap)
+{
+ return checkRectangles(aBitmap, true);
+}
+
+TestResult OutputDeviceTestCommon::checkFilledRectangle(Bitmap& aBitmap, bool useLineColor)
+{
+ std::vector<Color> aExpected{ constBackgroundColor,
+ useLineColor ? constLineColor : constFillColor, constFillColor,
+ constFillColor, constFillColor };
+
+ BitmapScopedWriteAccess pAccess(aBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ for (size_t aLayerNumber = 0; aLayerNumber < aExpected.size(); aLayerNumber++)
+ {
+ tools::Long startX = aLayerNumber, endX = pAccess->Width() / 2 - aLayerNumber + 1;
+ tools::Long startY = aLayerNumber, endY = pAccess->Height() - aLayerNumber - 1;
+
+ for (tools::Long ptX = startX; ptX <= endX; ++ptX)
+ {
+ checkValue(pAccess, ptX, startY, aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors,
+ true);
+ checkValue(pAccess, ptX, endY, aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ for (tools::Long ptY = startY; ptY <= endY; ++ptY)
+ {
+ checkValue(pAccess, startX, ptY, aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors,
+ true);
+ checkValue(pAccess, endX, ptY, aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ }
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkFilled(Bitmap& rBitmap, tools::Rectangle aRectangle, Color aExpectedColor)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ for (tools::Long y = aRectangle.Top(); y < aRectangle.Top() + aRectangle.GetHeight(); y++)
+ {
+ for (tools::Long x = aRectangle.Left(); x < aRectangle.Left() + aRectangle.GetWidth(); x++)
+ {
+ checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false);
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkRectangles(Bitmap& aBitmap, std::vector<Color>& aExpectedColors)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ for (size_t i = 0; i < aExpectedColors.size(); i++)
+ {
+ TestResult eResult = checkRect(aBitmap, i, aExpectedColors[i]);
+
+ if (eResult == TestResult::Failed)
+ aReturnValue = TestResult::Failed;
+ if (eResult == TestResult::PassedWithQuirks && aReturnValue != TestResult::Failed)
+ aReturnValue = TestResult::PassedWithQuirks;
+ }
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestCommon::checkRectangle(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor)
+{
+ return checkRect(rBitmap, aLayerNumber, aExpectedColor);
+}
+
+tools::Rectangle OutputDeviceTestCommon::alignToCenter(tools::Rectangle aRect1, tools::Rectangle aRect2)
+{
+ Point aPoint((aRect1.GetWidth() / 2.0) - (aRect2.GetWidth() / 2.0),
+ (aRect1.GetHeight() / 2.0) - (aRect2.GetHeight() / 2.0));
+
+ return tools::Rectangle(aPoint, aRect2.GetSize());
+}
+
+TestResult OutputDeviceTestCommon::checkDiamond(Bitmap& rBitmap)
+{
+ return checkDiamondLine(rBitmap, 1, constLineColor);
+}
+
+void OutputDeviceTestCommon::createDiamondPoints(tools::Rectangle rRect, int nOffset,
+ Point& rPoint1, Point& rPoint2,
+ Point& rPoint3, Point& rPoint4)
+{
+ tools::Long midPointX = rRect.Left() + (rRect.Right() - rRect.Left()) / 2.0;
+ tools::Long midPointY = rRect.Top() + (rRect.Bottom() - rRect.Top()) / 2.0;
+
+ rPoint1 = Point(midPointX , midPointY - nOffset);
+ rPoint2 = Point(midPointX + nOffset, midPointY );
+ rPoint3 = Point(midPointX , midPointY + nOffset);
+ rPoint4 = Point(midPointX - nOffset, midPointY );
+}
+
+tools::Polygon OutputDeviceTestCommon::createDropShapePolygon()
+{
+ tools::Polygon aPolygon(15);
+
+ aPolygon.SetPoint(Point(10, 2), 0);
+ aPolygon.SetFlags(0, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(14, 2), 1);
+ aPolygon.SetFlags(1, PolyFlags::Control);
+ aPolygon.SetPoint(Point(18, 6), 2);
+ aPolygon.SetFlags(2, PolyFlags::Control);
+ aPolygon.SetPoint(Point(18, 10), 3);
+
+ aPolygon.SetFlags(3, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(18, 10), 4);
+ aPolygon.SetFlags(4, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(18, 14), 5);
+ aPolygon.SetFlags(5, PolyFlags::Control);
+ aPolygon.SetPoint(Point(14, 18), 6);
+ aPolygon.SetFlags(6, PolyFlags::Control);
+ aPolygon.SetPoint(Point(10, 18), 7);
+ aPolygon.SetFlags(7, PolyFlags::Normal);
+
+ aPolygon.SetPoint(Point(10, 18), 8);
+ aPolygon.SetFlags(8, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(6, 18), 9);
+ aPolygon.SetFlags(9, PolyFlags::Control);
+ aPolygon.SetPoint(Point(2, 14), 10);
+ aPolygon.SetFlags(10, PolyFlags::Control);
+ aPolygon.SetPoint(Point(2, 10), 11);
+ aPolygon.SetFlags(11, PolyFlags::Normal);
+
+ aPolygon.SetPoint(Point(2, 10), 12);
+ aPolygon.SetFlags(12, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(2, 2), 13);
+ aPolygon.SetFlags(13, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(10, 2), 14);
+ aPolygon.SetFlags(14, PolyFlags::Normal);
+
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ return aPolygon;
+}
+
+basegfx::B2DPolygon OutputDeviceTestCommon::createHalfEllipsePolygon()
+{
+ basegfx::B2DPolygon aPolygon;
+
+ aPolygon.append({ 9.0, 1.0 });
+ aPolygon.append({ 17.0, 10.0 });
+ aPolygon.append({ 1.0, 10.0 });
+ aPolygon.setClosed(true);
+
+ aPolygon.setControlPoints(0, { 1.5, 1.5 }, { 16.5, 1.5 });
+
+ return aPolygon;
+}
+
+tools::Polygon OutputDeviceTestCommon::createClosedBezierLoop(const tools::Rectangle& rRect)
+{
+ tools::Long minX = rRect.Left();
+ tools::Long maxX = rRect.Right() - 2;
+ tools::Long minY = rRect.Top();
+ tools::Long maxY = rRect.Bottom() - 2;
+
+ tools::Polygon aPolygon(4);
+
+ aPolygon.SetPoint(Point((maxX / 2.0), maxY), 0);
+ aPolygon.SetFlags(0, PolyFlags::Normal);
+ aPolygon.SetPoint(Point(maxX, minY), 1);
+ aPolygon.SetFlags(1, PolyFlags::Control);
+ aPolygon.SetPoint(Point(minX, minY), 2);
+ aPolygon.SetFlags(2, PolyFlags::Control);
+ aPolygon.SetPoint(Point((maxX / 2.0), maxY), 3);
+ aPolygon.SetFlags(3, PolyFlags::Normal);
+
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ return aPolygon;
+}
+
+basegfx::B2DPolygon OutputDeviceTestCommon::createOpenPolygon(const tools::Rectangle& rRect, int nOffset)
+{
+ int nMidOffset = rRect.GetWidth() / 2;
+ basegfx::B2DPolygon aPolygon{
+ basegfx::B2DPoint(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Top() + nOffset - 1),
+ basegfx::B2DPoint(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Bottom() - nOffset + 1),
+ basegfx::B2DPoint(rRect.Right() - nMidOffset - nOffset / 3, rRect.Bottom() - nOffset + 1),
+ basegfx::B2DPoint(rRect.Right() - nMidOffset - nOffset / 3, rRect.Top() + nOffset - 1),
+ };
+ aPolygon.setClosed(false);
+ return aPolygon;
+}
+
+basegfx::B2DPolygon OutputDeviceTestCommon::createOpenBezier()
+{
+ basegfx::B2DPolygon aPolygon;
+
+ aPolygon.append({ 5.0, 2.0 });
+ aPolygon.append({ 3.0, 14.0 });
+ aPolygon.setClosed(false);
+
+ aPolygon.setControlPoints(0, { 15.0, 2.0 }, { 15.0, 15.0 });
+
+ return aPolygon;
+}
+
+TestResult OutputDeviceTestCommon::checkDropShape(Bitmap& rBitmap, bool aEnableAA)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ std::map<std::pair<int, int>, bool> SetPixels
+ = { { { 2, 2 }, true }, { { 3, 2 }, true }, { { 4, 2 }, true }, { { 5, 2 }, true },
+ { { 6, 2 }, true }, { { 7, 2 }, true }, { { 8, 2 }, true }, { { 9, 2 }, true },
+ { { 10, 2 }, true }, { { 11, 2 }, true }, { { 12, 2 }, true }, { { 2, 3 }, true },
+ { { 13, 3 }, true }, { { 14, 3 }, true }, { { 2, 4 }, true }, { { 15, 4 }, true },
+ { { 2, 5 }, true }, { { 16, 5 }, true }, { { 2, 6 }, true }, { { 17, 6 }, true },
+ { { 2, 7 }, true }, { { 17, 7 }, true }, { { 2, 8 }, true }, { { 18, 8 }, true },
+ { { 2, 9 }, true }, { { 18, 9 }, true }, { { 2, 10 }, true }, { { 18, 10 }, true },
+ { { 2, 11 }, true }, { { 18, 11 }, true }, { { 2, 12 }, true }, { { 18, 12 }, true },
+ { { 3, 13 }, true }, { { 17, 13 }, true }, { { 3, 14 }, true }, { { 17, 14 }, true },
+ { { 4, 15 }, true }, { { 16, 15 }, true }, { { 5, 16 }, true }, { { 15, 16 }, true },
+ { { 6, 17 }, true }, { { 7, 17 }, true }, { { 13, 17 }, true }, { { 14, 17 }, true },
+ { { 8, 18 }, true }, { { 9, 18 }, true }, { { 10, 18 }, true }, { { 11, 18 }, true },
+ { { 12, 18 }, true } };
+
+ for (tools::Long x = 0; x < pAccess->Width(); x++)
+ {
+ for (tools::Long y = 0; y < pAccess->Height(); y++)
+ {
+ if (SetPixels[{ x, y }])
+ {
+ if (aEnableAA)
+ {
+ // coverity[swapped_arguments : FALSE] - this is in the correct order
+ checkValueAA(pAccess, y, x, constLineColor, nNumberOfQuirks, nNumberOfErrors);
+ }
+ else
+ checkValue(pAccess, y, x, constLineColor, nNumberOfQuirks, nNumberOfErrors,
+ true);
+ }
+ else
+ {
+ if (!aEnableAA)
+ checkValue(pAccess, y, x, constBackgroundColor, nNumberOfQuirks, nNumberOfErrors,
+ true);
+ }
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+void OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(tools::Rectangle rRect,
+ Point& rHorizontalLinePoint1, Point& rHorizontalLinePoint2,
+ Point& rVerticalLinePoint1, Point& rVerticalLinePoint2,
+ Point& rDiagonalLinePoint1, Point& rDiagonalLinePoint2)
+{
+ rHorizontalLinePoint1 = Point(4, 1);
+ rHorizontalLinePoint2 = Point(rRect.Right() - 1, 1);
+
+ rVerticalLinePoint1 = Point(1, 4);
+ rVerticalLinePoint2 = Point(1,rRect.Bottom() - 1);
+
+ rDiagonalLinePoint1 = Point(1, 1);
+ rDiagonalLinePoint2 = Point(rRect.Right() - 1, rRect.Bottom() - 1);
+}
+
+TestResult OutputDeviceTestCommon::checkBezier(Bitmap& rBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor
+ };
+ // Check the bezier doesn't go over to the margins first
+ // TODO extend the check with more exact assert
+ return checkRectangles(rBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestCommon::checkHalfEllipse(Bitmap& rBitmap, bool aEnableAA)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ std::map<std::pair<tools::Long, tools::Long>, bool> SetPixels = {
+ { { 8, 1 }, true }, { { 9, 1 }, true }, { { 10, 1 }, true }, { { 6, 2 }, true },
+ { { 7, 2 }, true }, { { 10, 2 }, true }, { { 4, 3 }, true }, { { 5, 3 }, true },
+ { { 10, 3 }, true }, { { 3, 4 }, true }, { { 10, 4 }, true }, { { 2, 5 }, true },
+ { { 10, 5 }, true }, { { 2, 6 }, true }, { { 10, 6 }, true }, { { 1, 7 }, true },
+ { { 10, 7 }, true }, { { 1, 8 }, true }, { { 10, 8 }, true }, { { 1, 9 }, true },
+ { { 10, 9 }, true }, { { 1, 10 }, true }, { { 10, 10 }, true }, { { 1, 11 }, true },
+ { { 10, 11 }, true }, { { 2, 12 }, true }, { { 10, 12 }, true }, { { 2, 13 }, true },
+ { { 10, 13 }, true }, { { 3, 14 }, true }, { { 10, 14 }, true }, { { 4, 15 }, true },
+ { { 5, 15 }, true }, { { 10, 15 }, true }, { { 6, 16 }, true }, { { 7, 16 }, true },
+ { { 10, 16 }, true }, { { 8, 17 }, true }, { { 9, 17 }, true }, { { 10, 17 }, true }
+ };
+
+ for (tools::Long x = 0; x < pAccess->Width(); x++)
+ {
+ for (tools::Long y = 0; y < pAccess->Height(); ++y)
+ {
+ // coverity[swapped_arguments : FALSE] - this is in the correct order
+ if (SetPixels[{ y, x }])
+ {
+ if (aEnableAA)
+ checkValueAA(pAccess, x, y, constLineColor, nNumberOfQuirks, nNumberOfErrors);
+ else
+ checkValue(pAccess, x, y, constLineColor, nNumberOfQuirks, nNumberOfErrors,
+ true);
+ }
+ else
+ {
+ if (!aEnableAA)
+ checkValue(pAccess, x, y, constBackgroundColor, nNumberOfQuirks,
+ nNumberOfErrors, true);
+ }
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkClosedBezier(Bitmap& rBitmap)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ std::map<std::pair<tools::Long, tools::Long>, bool> SetPixels
+ = { { { 3, 8 }, true }, { { 3, 9 }, true }, { { 3, 10 }, true }, { { 4, 7 }, true },
+ { { 4, 8 }, true }, { { 4, 9 }, true }, { { 4, 10 }, true }, { { 4, 11 }, true },
+ { { 5, 7 }, true }, { { 5, 11 }, true }, { { 6, 6 }, true }, { { 6, 12 }, true },
+ { { 7, 6 }, true }, { { 7, 12 }, true }, { { 8, 7 }, true }, { { 8, 11 }, true },
+ { { 9, 7 }, true }, { { 9, 11 }, true }, { { 10, 7 }, true }, { { 10, 11 }, true },
+ { { 11, 8 }, true }, { { 11, 9 }, true }, { { 11, 10 }, true }, { { 12, 8 }, true },
+ { { 12, 9 }, true }, { { 12, 10 }, true }, { { 13, 9 }, true } };
+
+ for (tools::Long x = 0; x < pAccess->Width(); x++)
+ {
+ for (tools::Long y = 0; y < pAccess->Height(); ++y)
+ {
+ // coverity[swapped_arguments : FALSE] - this is in the correct order
+ if (SetPixels[{ y, x }])
+ {
+ checkValue(pAccess, x, y, constLineColor, nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ else
+ {
+ checkValue(pAccess, x, y, constBackgroundColor, nNumberOfQuirks, nNumberOfErrors,
+ true);
+ }
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0 || !checkConvexHullProperty(rBitmap, constLineColor, 2, 2))
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkOpenBezier(Bitmap& rBitmap)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ std::map<std::pair<int, int>, bool> SetPixels
+ = { { { 14, 3 }, true }, { { 14, 4 }, true }, { { 14, 5 }, true }, { { 3, 6 }, true },
+ { { 4, 6 }, true }, { { 14, 6 }, true }, { { 4, 7 }, true }, { { 5, 7 }, true },
+ { { 13, 7 }, true }, { { 6, 8 }, true }, { { 7, 8 }, true }, { { 12, 8 }, true },
+ { { 13, 8 }, true }, { { 8, 9 }, true }, { { 9, 9 }, true }, { { 10, 9 }, true },
+ { { 11, 9 }, true }, { { 12, 9 }, true } };
+
+ for (tools::Long x = 0; x < pAccess->Width(); x++)
+ {
+ for (tools::Long y = 0; y < pAccess->Height(); ++y)
+ {
+ // coverity[swapped_arguments : FALSE] - this is in the correct order
+ if (SetPixels[{ y, x }])
+ {
+ checkValue(pAccess, x, y, constLineColor, nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ else
+ {
+ checkValue(pAccess, x, y, constBackgroundColor, nNumberOfQuirks, nNumberOfErrors,
+ true);
+ }
+ }
+ }
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0 || !checkConvexHullProperty(rBitmap, constLineColor, 2, 5))
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkFilledAsymmetricalDropShape(Bitmap& rBitmap)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ std::map<std::pair<tools::Long, tools::Long>, bool> SetPixels
+ = { { { 2, 2 }, true }, { { 3, 2 }, true }, { { 4, 2 }, true }, { { 5, 2 }, true },
+ { { 6, 2 }, true }, { { 7, 2 }, true }, { { 8, 2 }, true }, { { 9, 2 }, true },
+ { { 10, 2 }, true }, { { 11, 2 }, true }, { { 2, 3 }, true }, { { 3, 3 }, true },
+ { { 4, 3 }, true }, { { 5, 3 }, true }, { { 6, 3 }, true }, { { 7, 3 }, true },
+ { { 8, 3 }, true }, { { 9, 3 }, true }, { { 10, 3 }, true }, { { 11, 3 }, true },
+ { { 12, 3 }, true }, { { 13, 3 }, true }, { { 2, 4 }, true }, { { 3, 4 }, true },
+ { { 4, 4 }, true }, { { 5, 4 }, true }, { { 6, 4 }, true }, { { 7, 4 }, true },
+ { { 8, 4 }, true }, { { 9, 4 }, true }, { { 10, 4 }, true }, { { 11, 4 }, true },
+ { { 12, 4 }, true }, { { 13, 4 }, true }, { { 14, 4 }, true }, { { 15, 4 }, true },
+ { { 2, 5 }, true }, { { 3, 5 }, true }, { { 4, 5 }, true }, { { 5, 5 }, true },
+ { { 6, 5 }, true }, { { 7, 5 }, true }, { { 8, 5 }, true }, { { 9, 5 }, true },
+ { { 10, 5 }, true }, { { 11, 5 }, true }, { { 12, 5 }, true }, { { 13, 5 }, true },
+ { { 14, 5 }, true }, { { 15, 5 }, true }, { { 2, 6 }, true }, { { 3, 6 }, true },
+ { { 4, 6 }, true }, { { 5, 6 }, true }, { { 6, 6 }, true }, { { 7, 6 }, true },
+ { { 8, 6 }, true }, { { 9, 6 }, true }, { { 10, 6 }, true }, { { 11, 6 }, true },
+ { { 12, 6 }, true }, { { 13, 6 }, true }, { { 14, 6 }, true }, { { 15, 6 }, true },
+ { { 16, 6 }, true }, { { 2, 7 }, true }, { { 3, 7 }, true }, { { 4, 7 }, true },
+ { { 5, 7 }, true }, { { 6, 7 }, true }, { { 7, 7 }, true }, { { 8, 7 }, true },
+ { { 9, 7 }, true }, { { 10, 7 }, true }, { { 11, 7 }, true }, { { 12, 7 }, true },
+ { { 13, 7 }, true }, { { 14, 7 }, true }, { { 15, 7 }, true }, { { 16, 7 }, true },
+ { { 2, 8 }, true }, { { 3, 8 }, true }, { { 4, 8 }, true }, { { 5, 8 }, true },
+ { { 6, 8 }, true }, { { 7, 8 }, true }, { { 8, 8 }, true }, { { 9, 8 }, true },
+ { { 10, 8 }, true }, { { 11, 8 }, true }, { { 12, 8 }, true }, { { 13, 8 }, true },
+ { { 14, 8 }, true }, { { 15, 8 }, true }, { { 16, 8 }, true }, { { 17, 8 }, true },
+ { { 2, 9 }, true }, { { 3, 9 }, true }, { { 4, 9 }, true }, { { 5, 9 }, true },
+ { { 6, 9 }, true }, { { 7, 9 }, true }, { { 8, 9 }, true }, { { 9, 9 }, true },
+ { { 10, 9 }, true }, { { 11, 9 }, true }, { { 12, 9 }, true }, { { 13, 9 }, true },
+ { { 14, 9 }, true }, { { 15, 9 }, true }, { { 16, 9 }, true }, { { 17, 9 }, true },
+ { { 2, 10 }, true }, { { 3, 10 }, true }, { { 4, 10 }, true }, { { 5, 10 }, true },
+ { { 6, 10 }, true }, { { 7, 10 }, true }, { { 8, 10 }, true }, { { 9, 10 }, true },
+ { { 10, 10 }, true }, { { 11, 10 }, true }, { { 12, 10 }, true }, { { 13, 10 }, true },
+ { { 14, 10 }, true }, { { 15, 10 }, true }, { { 16, 10 }, true }, { { 17, 10 }, true },
+ { { 2, 11 }, true }, { { 3, 11 }, true }, { { 4, 11 }, true }, { { 5, 11 }, true },
+ { { 6, 11 }, true }, { { 7, 11 }, true }, { { 8, 11 }, true }, { { 9, 11 }, true },
+ { { 10, 11 }, true }, { { 11, 11 }, true }, { { 12, 11 }, true }, { { 13, 11 }, true },
+ { { 14, 11 }, true }, { { 15, 11 }, true }, { { 16, 11 }, true }, { { 17, 11 }, true },
+ { { 3, 12 }, true }, { { 4, 12 }, true }, { { 5, 12 }, true }, { { 6, 12 }, true },
+ { { 7, 12 }, true }, { { 8, 12 }, true }, { { 9, 12 }, true }, { { 10, 12 }, true },
+ { { 11, 12 }, true }, { { 12, 12 }, true }, { { 13, 12 }, true }, { { 14, 12 }, true },
+ { { 15, 12 }, true }, { { 16, 12 }, true }, { { 3, 13 }, true }, { { 4, 13 }, true },
+ { { 5, 13 }, true }, { { 6, 13 }, true }, { { 7, 13 }, true }, { { 8, 13 }, true },
+ { { 9, 13 }, true }, { { 10, 13 }, true }, { { 11, 13 }, true }, { { 12, 13 }, true },
+ { { 13, 13 }, true }, { { 14, 13 }, true }, { { 15, 13 }, true }, { { 16, 13 }, true },
+ { { 4, 14 }, true }, { { 5, 14 }, true }, { { 6, 14 }, true }, { { 7, 14 }, true },
+ { { 8, 14 }, true }, { { 9, 14 }, true }, { { 10, 14 }, true }, { { 11, 14 }, true },
+ { { 12, 14 }, true }, { { 13, 14 }, true }, { { 14, 14 }, true }, { { 15, 14 }, true },
+ { { 5, 15 }, true }, { { 6, 15 }, true }, { { 7, 15 }, true }, { { 8, 15 }, true },
+ { { 9, 15 }, true }, { { 10, 15 }, true }, { { 11, 15 }, true }, { { 12, 15 }, true },
+ { { 13, 15 }, true }, { { 14, 15 }, true }, { { 15, 15 }, true }, { { 6, 16 }, true },
+ { { 7, 16 }, true }, { { 8, 16 }, true }, { { 9, 16 }, true }, { { 10, 16 }, true },
+ { { 11, 16 }, true }, { { 12, 16 }, true }, { { 13, 16 }, true }, { { 8, 17 }, true },
+ { { 9, 17 }, true }, { { 10, 17 }, true }, { { 11, 17 }, true } };
+
+ for (tools::Long x = 0; x < pAccess->Width(); x++)
+ {
+ for (tools::Long y = 0; y < pAccess->Height(); ++y)
+ {
+ if (SetPixels[{ x, y }])
+ {
+ checkValue(pAccess, y, x, constFillColor, nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ else
+ {
+ checkValue(pAccess, y, x, constBackgroundColor, nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkTextLocation(Bitmap& rBitmap)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+
+ //The limit to which error would be tolerated.
+ tools::Long textThreshold = 3;
+ tools::Long textWidth = 3, textHeight = 8;
+ tools::Long deviationX = 0, deviationY = 0;
+ tools::Long verticalStart = 0, verticalEnd = 0;
+ tools::Long horizontalStart = 0, horizontalEnd = 0;
+ tools::Long midX = pAccess->Width() / 2.0;
+ tools::Long midY = pAccess->Height() / 2.0;
+ bool insideFlag = false;
+
+ //Traversing horizontally
+ for (tools::Long x = 0, y = pAccess->Height() / 2.0; x < pAccess->Width(); ++x)
+ {
+ if (pAccess->GetPixel(y, x) != constBackgroundColor)
+ {
+ if (!insideFlag)
+ {
+ horizontalStart = x;
+ insideFlag = true;
+ }
+ else
+ {
+ horizontalEnd = x;
+ }
+ }
+ }
+
+ deviationX = abs(midX - horizontalStart);
+ midY -= midY / 2.0;
+ midY += 1;
+
+ insideFlag = false;
+ //Traversing vertically
+ for (tools::Long x = 0, y = pAccess->Height() / 2.0; x < pAccess->Height(); ++x)
+ {
+ if (pAccess->GetPixel(x, y) != constBackgroundColor)
+ {
+ if (!insideFlag)
+ {
+ verticalStart = x;
+ insideFlag = true;
+ }
+ else
+ {
+ verticalEnd = x;
+ }
+ }
+ }
+
+ deviationY = abs(midY - verticalStart);
+
+ if (deviationX != 0 || deviationY != 0 || abs(horizontalStart - horizontalEnd) + 1 != textWidth
+ || abs(verticalStart - verticalEnd) + 1 != textHeight)
+ {
+ aResult = TestResult::PassedWithQuirks;
+ }
+
+ if (deviationX > textThreshold || deviationY > textThreshold
+ || abs((abs(horizontalStart - horizontalEnd) + 1) - textWidth) > textThreshold
+ || abs((abs(verticalStart - verticalEnd) + 1) - textHeight) > textThreshold)
+ {
+ aResult = TestResult::Failed;
+ }
+
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkIntersectingRecs(Bitmap& rBitmap, int aLayerNumber,
+ Color aExpected)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ for (int x = 4; x <= 19; ++x)
+ {
+ checkValue(pAccess, x, aLayerNumber, aExpected, nNumberOfQuirks, nNumberOfErrors, true);
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkEvenOddRuleInIntersectingRecs(Bitmap& rBitmap)
+{
+ /*
+ The even-odd rule would be tested via the below pattern as layers both of the
+ constFillColor & constBackgroundColor appears in an even-odd fashion.
+ */
+ std::vector<Color> aExpectedColors
+ = { constBackgroundColor, constBackgroundColor, constLineColor, constFillColor,
+ constFillColor, constLineColor, constBackgroundColor, constBackgroundColor,
+ constLineColor, constFillColor, constFillColor, constLineColor,
+ constBackgroundColor, constBackgroundColor, constLineColor, constFillColor,
+ constFillColor, constLineColor, constBackgroundColor, constBackgroundColor,
+ constLineColor, constFillColor, constLineColor };
+
+ TestResult aReturnValue = TestResult::Passed;
+ for (size_t i = 0; i < aExpectedColors.size(); i++)
+ {
+ TestResult eResult = checkIntersectingRecs(rBitmap, i, aExpectedColors[i]);
+
+ if (eResult == TestResult::Failed)
+ aReturnValue = TestResult::Failed;
+ if (eResult == TestResult::PassedWithQuirks && aReturnValue != TestResult::Failed)
+ aReturnValue = TestResult::PassedWithQuirks;
+ }
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestCommon::checkOpenPolygon(Bitmap& rBitmap, bool aEnableAA)
+{
+ std::vector<Color> aExpected = { constBackgroundColor, constLineColor, constLineColor };
+
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ for (size_t aLayerNumber = 0; aLayerNumber < aExpected.size(); aLayerNumber++)
+ {
+ tools::Long startX = aLayerNumber + 1, endX = pAccess->Width() / 2 - aLayerNumber;
+ tools::Long startY = aLayerNumber + 2, endY = pAccess->Height() - aLayerNumber - 3;
+
+ for (tools::Long ptX = startX; ptX <= endX; ++ptX)
+ {
+ if (aEnableAA)
+ {
+ checkValueAA(pAccess, ptX, endY - (aLayerNumber == 2 ? 2 : 0),
+ aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors);
+ }
+ else
+ {
+ checkValue(pAccess, ptX, endY - (aLayerNumber == 2 ? 2 : 0),
+ aExpected[aLayerNumber], nNumberOfQuirks, nNumberOfErrors, true);
+ }
+ }
+ for (tools::Long ptY = startY + (aLayerNumber == 2 ? 2 : 0);
+ ptY <= endY - (aLayerNumber == 2 ? 2 : 0); ++ptY)
+ {
+ if (aEnableAA)
+ {
+ checkValueAA(pAccess, startX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors);
+ checkValueAA(pAccess, endX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors);
+ }
+ else
+ {
+ checkValue(pAccess, startX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors, true);
+ checkValue(pAccess, endX, ptY, aExpected[aLayerNumber], nNumberOfQuirks,
+ nNumberOfErrors, true);
+ }
+ }
+ }
+
+ if (nNumberOfQuirks > 0)
+ aResult = TestResult::PassedWithQuirks;
+ if (nNumberOfErrors > 0)
+ aResult = TestResult::Failed;
+ return aResult;
+}
+
+// Check 'count' pixels from (x,y) in (addX,addY) direction, the color values must not decrease.
+static bool checkGradient(BitmapScopedWriteAccess& pAccess, int x, int y, int count, int addX, int addY)
+{
+ const bool bColorize = false;
+ Color maxColor = COL_BLACK;
+ for( int i = 0; i < count; ++i )
+ {
+ Color color = pAccess->GetPixel(y, x);
+ if( color.GetRed() < maxColor.GetRed() || color.GetGreen() < maxColor.GetGreen() || color.GetBlue() < maxColor.GetBlue())
+ {
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_RED);
+ return false;
+ }
+ maxColor = color;
+ if (bColorize)
+ pAccess->SetPixel(y, x, COL_LIGHTGREEN);
+ x += addX;
+ y += addY;
+ }
+ return true;
+}
+
+TestResult OutputDeviceTestCommon::checkLinearGradient(Bitmap& bitmap)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // The lowest line is missing in the default VCL implementation => quirk.
+ checkValue(pAccess, 1, 10, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, true, 255 / 10);
+ checkValue(pAccess, 10, 10, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, true, 255 / 10);
+ for(int y = 1; y < 10; ++y)
+ {
+ checkValue(pAccess, 1, y, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10);
+ checkValue(pAccess, 10, y, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10);
+ }
+ for(int y = 1; y < 10; ++y)
+ if( !checkGradient( pAccess, 10, y, 10, -1, 0 ))
+ return TestResult::Failed;
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkLinearGradientAngled(Bitmap& bitmap)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // The top-left pixel is not white but gray in the default VCL implementation => quirk.
+ checkValue(pAccess, 1, 1, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 50);
+ checkValue(pAccess, 10, 10, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 0, 255 / 10); // Bottom-right.
+ // Main diagonal.
+ if( !checkGradient( pAccess, 10, 10, 10, -1, -1 ))
+ return TestResult::Failed;
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return TestResult::Passed;
+}
+
+TestResult OutputDeviceTestCommon::checkLinearGradientBorder(Bitmap& bitmap)
+{
+ TestResult aResult = TestResult::Passed;
+ // Top half is border.
+ checkResult(checkFilled(bitmap, tools::Rectangle(Point(1, 1), Size(10, 5)), COL_WHITE), aResult);
+ BitmapScopedWriteAccess pAccess(bitmap);
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+ for(int x = 1; x <= 10; ++x)
+ {
+ checkValue(pAccess, x, 10, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ if( !checkGradient( pAccess, x, 10, 5, 0, -1 ))
+ return TestResult::Failed;
+ }
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkLinearGradientIntensity(Bitmap& bitmap)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ for(int x = 1; x <= 10; ++x)
+ {
+ // The gradient starts at half intensity, i.e. white's 255's are halved.
+ checkValue(pAccess, x, 1, Color(128,128,128), nNumberOfQuirks, nNumberOfErrors, false, 10);
+ checkValue(pAccess, x, 10, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10);
+ if( !checkGradient( pAccess, x, 10, 10, 0, -1 ))
+ return TestResult::Failed;
+ }
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkLinearGradientSteps(Bitmap& bitmap)
+{
+ // Reuse the basic linear gradient check.
+ TestResult aResult = checkLinearGradient(bitmap);
+ // Only 4 steps in the gradient, there should be only 4 colors.
+ if( collectColors( bitmap, tools::Rectangle( Point( 1, 1 ), Size( 10, 10 ))).size() != 4 )
+ return TestResult::Failed;
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkAxialGradient(Bitmap& bitmap)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ for(int y = 1; y <= 11; ++y)
+ {
+ // Middle horizontal line is white, gradients to the sides.
+ checkValue(pAccess, 6, y, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 1, y, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 11, y, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ if( !checkGradient( pAccess, 1, y, 6, 1, 0 ))
+ return TestResult::Failed;
+ if( !checkGradient( pAccess, 11, y, 6, -1, 0 ))
+ return TestResult::Failed;
+ }
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkRadialGradient(Bitmap& bitmap)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+ // The default VCL implementation is off-center in the direction to the top-left.
+ // This means not all corners will be pure white => quirks.
+ checkValue(pAccess, 1, 1, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 2);
+ checkValue(pAccess, 1, 10, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 10, 1, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 10, 10, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ // And not all centers will be pure black => quirks.
+ checkValue(pAccess, 5, 5, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 5, 6, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 3);
+ checkValue(pAccess, 6, 5, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 3);
+ checkValue(pAccess, 6, 6, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 2);
+ // Check diagonals, from the offset center.
+ if(!checkGradient(pAccess, 5, 5, 5, -1, -1))
+ return TestResult::Failed;
+ if(!checkGradient(pAccess, 5, 5, 6, 1, 1))
+ return TestResult::Failed;
+ if(!checkGradient(pAccess, 5, 5, 5, 1, -1))
+ return TestResult::Failed;
+ if(!checkGradient(pAccess, 5, 5, 5, -1, 1))
+ return TestResult::Failed;
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkRadialGradientOfs(Bitmap& bitmap)
+{
+ BitmapScopedWriteAccess pAccess(bitmap);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+ checkValue(pAccess, 1, 1, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 10, 1, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 1, 10, COL_WHITE, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ checkValue(pAccess, 10, 10, COL_BLACK, nNumberOfQuirks, nNumberOfErrors, 255 / 10, 255 / 5);
+ // Check gradients from the center (=bottom-right corner).
+ if(!checkGradient(pAccess, 10, 10, 10, -1, -1))
+ return TestResult::Failed;
+ if(!checkGradient(pAccess, 10, 10, 10, -1, 0))
+ return TestResult::Failed;
+ if(!checkGradient(pAccess, 10, 10, 10, 0, -1))
+ return TestResult::Failed;
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+constexpr int CAPSHRINK = 25;
+constexpr int CAPWIDTH = 20;
+TestResult OutputDeviceTestCommon::checkLineCap(Bitmap& rBitmap, css::drawing::LineCap lineCap)
+{
+ BitmapScopedWriteAccess access(rBitmap);
+ tools::Rectangle rectangle( Point( 0, 0 ), Size( 101, 101 ));
+ rectangle.shrink(CAPSHRINK);
+ rectangle = tools::Rectangle( Point(rectangle.LeftCenter().getX(), rectangle.LeftCenter().getY() - CAPWIDTH / 2),
+ Point(rectangle.RightCenter().getX(), rectangle.RightCenter().getY() + CAPWIDTH / 2));
+ rectangle.shrink(1);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // the line itself
+ checkValue(access, rectangle.TopLeft(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.TopRight(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.BottomLeft(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.BottomRight(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+
+ // the cap in the middle
+ Color color = ( lineCap == css::drawing::LineCap_BUTT ) ? constBackgroundColor : constLineColor;
+ checkValue(access, rectangle.LeftCenter() - Point(CAPWIDTH/2, 0), color, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.RightCenter() + Point(CAPWIDTH/2, 0), color, nNumberOfQuirks, nNumberOfErrors, false);
+
+ // the cap corners
+ color = ( lineCap == css::drawing::LineCap_SQUARE ) ? constLineColor : constBackgroundColor;
+ checkValue(access, rectangle.TopLeft() - Point(CAPWIDTH/2, 0), color, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.TopRight() + Point(CAPWIDTH/2, 0), color, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.BottomLeft() - Point(CAPWIDTH/2, 0), color, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle.BottomRight() + Point(CAPWIDTH/2, 0), color, nNumberOfQuirks, nNumberOfErrors, false);
+
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestCommon::checkLineJoin(Bitmap& rBitmap, basegfx::B2DLineJoin lineJoin)
+{
+ BitmapScopedWriteAccess access(rBitmap);
+ tools::Rectangle rectangle( Point( 0, 0 ), Size( 101, 101 ));
+ rectangle.shrink(CAPSHRINK);
+ tools::Rectangle rectangle1( Point(rectangle.TopLeft().getX(), rectangle.TopLeft().getY() - CAPWIDTH / 2),
+ Point(rectangle.TopRight().getX(), rectangle.TopRight().getY() + CAPWIDTH / 2));
+ tools::Rectangle rectangle2( Point(rectangle.TopRight().getX() - CAPWIDTH / 2, rectangle.TopRight().getY()),
+ Point(rectangle.BottomRight().getX() + CAPWIDTH / 2, rectangle.BottomRight().getY()));
+ rectangle1.shrink(1);
+ rectangle2.shrink(1);
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // the lines themselves
+ checkValue(access, rectangle1.TopLeft(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle1.TopRight(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle1.BottomLeft(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle1.BottomRight(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle2.TopLeft(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle2.TopRight(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle2.BottomLeft(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+ checkValue(access, rectangle2.BottomRight(), constLineColor, nNumberOfQuirks, nNumberOfErrors, false);
+
+ // Only miter has the corner point.
+ Color color = ( lineJoin == basegfx::B2DLineJoin::Miter ) ? constLineColor : constBackgroundColor;
+ checkValue(access, rectangle2.Right(), rectangle1.Top(), color, nNumberOfQuirks, nNumberOfErrors, false);
+
+ // Round reaches a bit past the diagonal.
+ Point midDiagonal = (Point( rectangle2.Right(), rectangle1.Top()) + rectangle.TopRight()) / 2;
+ if( lineJoin == basegfx::B2DLineJoin::Round)
+ color = constLineColor;
+ checkValue(access, midDiagonal + Point( 2, -2 ), color, nNumberOfQuirks, nNumberOfErrors, false);
+ // Bevel is the diagonal.
+ if( lineJoin == basegfx::B2DLineJoin::Bevel)
+ color = constLineColor;
+ checkValue(access, midDiagonal + Point( -1, 1 ), color, nNumberOfQuirks, nNumberOfErrors, false);
+ // Everything except None has at least some line join.
+ checkValue(access, rectangle.TopRight() + Point( 1, -1 ), color, nNumberOfQuirks, nNumberOfErrors, false);
+
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aResult);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aResult);
+ return aResult;
+}
+
+TestResult OutputDeviceTestAnotherOutDev::checkDrawOutDev(Bitmap& rBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor,
+ constFillColor, constFillColor, constFillColor, constFillColor, constFillColor
+ };
+ return checkRectangles(rBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestAnotherOutDev::checkDrawOutDevScaledClipped(Bitmap& rBitmap)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ TestResult eResult;
+
+ eResult = checkRect(rBitmap, 0, constBackgroundColor); // outer line
+ checkResult(eResult, aReturnValue);
+ eResult = checkRect(rBitmap, 1, constBackgroundColor); // next outer line
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(2, 2), Size(4, 8)), constBackgroundColor);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(6, 2), Size(4, 8)), constFillColor);
+ checkResult(eResult, aReturnValue);
+
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestAnotherOutDev::checkDrawOutDevSelf(Bitmap& rBitmap)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ TestResult eResult;
+
+ eResult = checkRect(rBitmap, 0, constBackgroundColor); // outer line
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(1, 1), Size(4, 4)), constBackgroundColor);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(8, 8), Size(4, 4)), constBackgroundColor);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(11, 1), Size(1, 1)), COL_YELLOW);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(7, 5), Size(1, 1)), COL_YELLOW);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(1, 11), Size(1, 1)), COL_YELLOW);
+ checkResult(eResult, aReturnValue);
+
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(1, 5), Size(6, 6)), constFillColor);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(2, 6), Size(6, 6)), constFillColor);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(5, 1), Size(6, 4)), constFillColor);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(8, 2), Size(4, 6)), constFillColor);
+ checkResult(eResult, aReturnValue);
+
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestAnotherOutDev::checkXOR(Bitmap& rBitmap)
+{
+ Color xorColor( constBackgroundColor.GetRed() ^ constFillColor.GetRed(),
+ constBackgroundColor.GetGreen() ^ constFillColor.GetGreen(),
+ constBackgroundColor.GetBlue() ^ constFillColor.GetBlue());
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, xorColor,
+ constBackgroundColor, constBackgroundColor,
+ constFillColor, constFillColor,
+ constFillColor
+ };
+ return checkRectangles(rBitmap, aExpected);
+}
+
+
+TestResult OutputDeviceTestBitmap::checkTransformedBitmap(Bitmap& rBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor,
+ COL_YELLOW, constFillColor, COL_YELLOW, constFillColor, constFillColor
+ };
+ return checkRectangles(rBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestBitmap::checkComplexTransformedBitmap(Bitmap& rBitmap)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ TestResult eResult;
+ eResult = checkRectangle(rBitmap, 0, constBackgroundColor); // outer line not affected
+ checkResult(eResult, aReturnValue);
+ // empty "corners" should not be affected
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(1, 11), Size(2, 2)), constBackgroundColor);
+ checkResult(eResult, aReturnValue);
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(14, 1), Size(2, 2)), constBackgroundColor);
+ // check the middle
+ eResult = checkFilled(rBitmap, tools::Rectangle(Point(4, 3), Size(9, 8)), constFillColor);
+ checkResult(eResult, aReturnValue);
+ checkResult(eResult, aReturnValue);
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+ BitmapScopedWriteAccess pAccess(rBitmap);
+ // starting and ending corner, headless draws with AA, so be lenient
+ checkValue(pAccess, 1, 1, constFillColor, nNumberOfQuirks, nNumberOfErrors, 0, 192);
+ checkValue(pAccess, 2, 2, constFillColor, nNumberOfQuirks, nNumberOfErrors, 0, 16);
+ checkValue(pAccess, 14, 11, constFillColor, nNumberOfQuirks, nNumberOfErrors, 0, 16);
+ checkValue(pAccess, 15, 12, constFillColor, nNumberOfQuirks, nNumberOfErrors, 0, 192);
+ if (nNumberOfQuirks > 0)
+ checkResult(TestResult::PassedWithQuirks, aReturnValue);
+ if (nNumberOfErrors > 0)
+ checkResult(TestResult::Failed, aReturnValue);
+ return aReturnValue;
+}
+
+TestResult OutputDeviceTestBitmap::checkTransformedBitmap8bppGreyScale(Bitmap& rBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ Color(0xC0,0xC0,0xC0), Color(0xC0,0xC0,0xC0),
+ Color(0xE2,0xE2,0xE2), Color(0xE,0xE,0xE), Color(0xE2,0xE2,0xE2), Color(0xE,0xE,0xE), Color(0xE,0xE,0xE)
+ };
+ return checkRectangles(rBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestBitmap::checkBitmapExWithAlpha(Bitmap& rBitmap)
+{
+ const Color aBlendedColor(0xEE, 0xEE, 0x33);
+
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor,
+ aBlendedColor, constBackgroundColor, constBackgroundColor,
+ aBlendedColor, constBackgroundColor
+ };
+ return checkRectangles(rBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestBitmap::checkMask(Bitmap& rBitmap)
+{
+ return checkRectangle(rBitmap);
+}
+
+TestResult OutputDeviceTestBitmap::checkBlend(const BitmapEx& rBitmapEx)
+{
+ const Color aBlendedColor(0xEE, 0xEE, 0x33);
+
+ std::vector<Color> aExpected
+ {
+ COL_WHITE, COL_WHITE, COL_YELLOW, constBackgroundColor,
+ constBackgroundColor, aBlendedColor, constBackgroundColor
+ };
+ Bitmap aBitmap(rBitmapEx.GetBitmap());
+ return checkRectangles(aBitmap, aExpected);
+}
+
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/gradient.cxx b/vcl/backendtest/outputdevice/gradient.cxx
new file mode 100644
index 000000000..ebb94fbaa
--- /dev/null
+++ b/vcl/backendtest/outputdevice/gradient.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+#include <vcl/gradient.hxx>
+
+namespace vcl::test
+{
+Bitmap OutputDeviceTestGradient::setupLinearGradient()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Linear, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetAngle(900_deg10);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupLinearGradientAngled()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Linear, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetAngle(450_deg10);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupLinearGradientBorder()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Linear, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetBorder(50);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupLinearGradientIntensity()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Linear, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetStartIntensity(50);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupLinearGradientSteps()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Linear, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetAngle(900_deg10);
+ aGradient.SetSteps(4);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupAxialGradient()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Axial, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetAngle(900_deg10);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupRadialGradient()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Radial, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestGradient::setupRadialGradientOfs()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle::Radial, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetOfsX(100); // Move center to the bottom-right corner.
+ aGradient.SetOfsY(100);
+ tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1,
+ maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1);
+ mpVirtualDevice->DrawGradient(aDrawRect, aGradient);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/line.cxx b/vcl/backendtest/outputdevice/line.cxx
new file mode 100644
index 000000000..5cb6db10a
--- /dev/null
+++ b/vcl/backendtest/outputdevice/line.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+
+#include <list>
+
+namespace vcl::test {
+
+namespace
+{
+
+void drawLineOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset)
+{
+
+ int nMidOffset = rRect.GetWidth()/2;
+ Point aLeftTop (rRect.Left() + nOffset - (nOffset+1)/2, rRect.Top() + nOffset - 1);
+ Point aRightTop (rRect.Right() - nMidOffset - nOffset/3, rRect.Top() + nOffset - 1);
+ Point aLeftBottom (rRect.Left() + nOffset - (nOffset+1)/2, rRect.Bottom() - nOffset + 1);
+ Point aRightBottom (rRect.Right() - nMidOffset - nOffset/3, rRect.Bottom() - nOffset + 1);
+
+ rDevice.DrawLine(aLeftTop, aRightTop);
+ rDevice.DrawLine(aRightTop, aRightBottom);
+ rDevice.DrawLine(aRightBottom, aLeftBottom);
+ rDevice.DrawLine(aLeftBottom, aLeftTop);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestLine::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupDiamond()
+{
+ initialSetup(11, 11, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aPoint1, aPoint2, aPoint3, aPoint4;
+ OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3, aPoint4);
+
+ mpVirtualDevice->DrawLine(aPoint1, aPoint2);
+ mpVirtualDevice->DrawLine(aPoint2, aPoint3);
+ mpVirtualDevice->DrawLine(aPoint3, aPoint4);
+ mpVirtualDevice->DrawLine(aPoint4, aPoint1);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupLines()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aHorizontalLinePoint1, aHorizontalLinePoint2;
+ Point aVerticalLinePoint1, aVerticalLinePoint2;
+ Point aDiagonalLinePoint1, aDiagonalLinePoint2;
+
+ OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
+ maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2,
+ aVerticalLinePoint1, aVerticalLinePoint2,
+ aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ mpVirtualDevice->DrawLine(aHorizontalLinePoint1, aHorizontalLinePoint2);
+ mpVirtualDevice->DrawLine(aVerticalLinePoint1, aVerticalLinePoint2);
+ mpVirtualDevice->DrawLine(aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupAALines()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetAntialiasing(AntialiasingFlags::Enable);
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aHorizontalLinePoint1, aHorizontalLinePoint2;
+ Point aVerticalLinePoint1, aVerticalLinePoint2;
+ Point aDiagonalLinePoint1, aDiagonalLinePoint2;
+
+ OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
+ maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2,
+ aVerticalLinePoint1, aVerticalLinePoint2,
+ aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ mpVirtualDevice->DrawLine(aHorizontalLinePoint1, aHorizontalLinePoint2);
+ mpVirtualDevice->DrawLine(aVerticalLinePoint1, aVerticalLinePoint2);
+ mpVirtualDevice->DrawLine(aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupDashedLine()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(2);
+
+ std::vector<double> stroke({ 2.0, 1.0 });
+ mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(),
+ basegfx::B2DPolygon{
+ basegfx::B2DPoint(rectangle.Left(), rectangle.Top()),
+ basegfx::B2DPoint(rectangle.Left(), rectangle.Bottom()),
+ basegfx::B2DPoint(rectangle.Right(), rectangle.Bottom()),
+ basegfx::B2DPoint(rectangle.Right(), rectangle.Top()),
+ basegfx::B2DPoint(rectangle.Left(), rectangle.Top())},
+ 1, 0, &stroke, basegfx::B2DLineJoin::NONE );
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+TestResult OutputDeviceTestLine::checkDashedLine(Bitmap& rBitmap)
+{
+ TestResult returnValue = TestResult::Passed;
+ for (int i = 0; i < 7; i++)
+ {
+ TestResult eResult = TestResult::Passed;
+ if( i == 2 )
+ {
+ // Build a sequence of pixels for the drawn rectangle border,
+ // check that they alternate appropriately (there should be
+ // normally 2 line, 1 background).
+ std::list< bool > dash; // true - line color, false - background
+ const int width = rBitmap.GetSizePixel().Width();
+ const int height = rBitmap.GetSizePixel().Height();
+ BitmapReadAccess access(rBitmap);
+ for( int x = 2; x < width - 2; ++x )
+ dash.push_back( access.GetPixel( 2, x ) == constLineColor );
+ for( int y = 3; y < height - 3; ++y )
+ dash.push_back( access.GetPixel( y, width - 3 ) == constLineColor );
+ for( int x = width - 3; x >= 2; --x )
+ dash.push_back( access.GetPixel( height - 3, x ) == constLineColor );
+ for( int y = height - 4; y >= 3; --y )
+ dash.push_back( access.GetPixel( y, 2 ) == constLineColor );
+ for( int x = 2; x < width - 2; ++x ) // repeat, to check also the corner
+ dash.push_back( access.GetPixel( 2, x ) == constLineColor );
+ bool last = false;
+ int lastCount = 0;
+ while( !dash.empty())
+ {
+ if( dash.front() == last )
+ {
+ ++lastCount;
+ if( lastCount > ( last ? 4 : 3 ))
+ eResult = TestResult::Failed;
+ else if( lastCount > ( last ? 3 : 2 ) && eResult != TestResult::Failed)
+ eResult = TestResult::PassedWithQuirks;
+ }
+ else
+ {
+ last = dash.front();
+ lastCount = 1;
+ }
+ dash.pop_front();
+ }
+ }
+ else
+ {
+ eResult = OutputDeviceTestCommon::checkRectangle(rBitmap, i, constBackgroundColor);
+ }
+
+ if (eResult == TestResult::Failed)
+ returnValue = TestResult::Failed;
+ if (eResult == TestResult::PassedWithQuirks && returnValue != TestResult::Failed)
+ returnValue = TestResult::PassedWithQuirks;
+ }
+ return returnValue;
+}
+
+constexpr int CAPSHRINK = 25;
+constexpr int CAPWIDTH = 20;
+Bitmap OutputDeviceTestLine::setupLineCap( css::drawing::LineCap lineCap )
+{
+ initialSetup(101, 101, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(CAPSHRINK);
+
+ const basegfx::B2DPolygon poly{
+ basegfx::B2DPoint(rectangle.LeftCenter().getX(), rectangle.LeftCenter().getY()),
+ basegfx::B2DPoint(rectangle.RightCenter().getX(), rectangle.RightCenter().getY())};
+
+ mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(),poly,
+ CAPWIDTH, 0, nullptr, basegfx::B2DLineJoin::NONE, lineCap );
+
+ mpVirtualDevice->SetLineColor(constFillColor);
+ mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), poly,
+ 0, 0, nullptr, basegfx::B2DLineJoin::NONE );
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestLine::setupLineJoin( basegfx::B2DLineJoin lineJoin )
+{
+ initialSetup(101, 101, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.shrink(CAPSHRINK);
+
+ const basegfx::B2DPolygon poly{
+ basegfx::B2DPoint(rectangle.TopLeft().getX(), rectangle.TopLeft().getY()),
+ basegfx::B2DPoint(rectangle.TopRight().getX(), rectangle.TopRight().getY()),
+ basegfx::B2DPoint(rectangle.BottomRight().getX(), rectangle.BottomRight().getY())};
+
+ mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), poly,
+ CAPWIDTH, 0, nullptr, lineJoin );
+
+ mpVirtualDevice->SetLineColor(constFillColor);
+ mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), poly,
+ 0, 0, nullptr, lineJoin );
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/outputdevice.cxx b/vcl/backendtest/outputdevice/outputdevice.cxx
new file mode 100644
index 000000000..ca58e006f
--- /dev/null
+++ b/vcl/backendtest/outputdevice/outputdevice.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test {
+
+Bitmap OutputDeviceTestAnotherOutDev::setupDrawOutDev()
+{
+ ScopedVclPtrInstance<VirtualDevice> pSourceDev;
+ Size aSourceSize(9, 9);
+ pSourceDev->SetOutputSizePixel(aSourceSize);
+ pSourceDev->SetBackground(Wallpaper(constFillColor));
+ pSourceDev->Erase();
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->DrawOutDev(Point(2, 2), aSourceSize, Point(), aSourceSize, *pSourceDev);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+
+Bitmap OutputDeviceTestAnotherOutDev::setupDrawOutDevScaledClipped()
+{
+ ScopedVclPtrInstance<VirtualDevice> pSourceDev;
+ Size aSourceSize(18, 18);
+ pSourceDev->SetOutputSizePixel(aSourceSize);
+ pSourceDev->SetBackground(Wallpaper(constFillColor));
+ pSourceDev->Erase();
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ tools::Rectangle rectangle = maVDRectangle;
+ rectangle.SetLeft(rectangle.GetWidth() / 2);
+ mpVirtualDevice->SetClipRegion(vcl::Region(rectangle));
+
+ mpVirtualDevice->DrawOutDev(Point(2, 2), aSourceSize / 2, Point(), aSourceSize, *pSourceDev);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestAnotherOutDev::setupDrawOutDevSelf()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ tools::Rectangle aDrawRectangle(maVDRectangle);
+ aDrawRectangle.shrink(3);
+ aDrawRectangle.Move( 2, -2 );
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+ mpVirtualDevice->SetLineColor(COL_YELLOW);
+ mpVirtualDevice->DrawPixel(aDrawRectangle.TopLeft() + Point(aDrawRectangle.GetWidth() - 1, 0));
+ mpVirtualDevice->DrawPixel(aDrawRectangle.TopLeft() + Point(0,aDrawRectangle.GetHeight() - 1));
+
+ // Intentionally overlap a bit.
+ mpVirtualDevice->DrawOutDev(Point(1, 5), aDrawRectangle.GetSize(),
+ Point(5,1), aDrawRectangle.GetSize(), *mpVirtualDevice);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestAnotherOutDev::setupXOR()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ tools::Rectangle aDrawRectangle(maVDRectangle);
+ aDrawRectangle.shrink(2);
+
+ tools::Rectangle aScissorRectangle(maVDRectangle);
+ aScissorRectangle.shrink(4);
+
+ mpVirtualDevice->SetRasterOp(RasterOp::Xor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+
+ mpVirtualDevice->SetRasterOp(RasterOp::N0);
+ mpVirtualDevice->SetFillColor(COL_BLACK);
+ mpVirtualDevice->DrawRect(aScissorRectangle);
+
+ mpVirtualDevice->SetRasterOp(RasterOp::Xor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+
+ mpVirtualDevice->SetRasterOp(RasterOp::Xor);
+ mpVirtualDevice->SetLineColor(constFillColor);
+ mpVirtualDevice->SetFillColor();
+ // Rectangle drawn twice is a no-op.
+ aDrawRectangle = maVDRectangle;
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+ // Rectangle drawn three times is like drawing once.
+ aDrawRectangle.shrink(1);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/pixel.cxx b/vcl/backendtest/outputdevice/pixel.cxx
new file mode 100644
index 000000000..3892160ef
--- /dev/null
+++ b/vcl/backendtest/outputdevice/pixel.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+namespace
+{
+void drawPixelOffset(OutputDevice& rDevice, tools::Rectangle const& rRect, int nOffset)
+{
+ int nMidOffset = rRect.GetWidth() / 2;
+ for (tools::Long x = 0 + nOffset / 2; x < (rRect.GetWidth() - nMidOffset); ++x)
+ {
+ tools::Long y1 = nOffset - 1;
+ tools::Long y2 = rRect.GetHeight() - nOffset;
+
+ rDevice.DrawPixel(Point(x, y1));
+ rDevice.DrawPixel(Point(x, y2));
+ }
+
+ for (tools::Long y = 0 + nOffset; y < (rRect.GetHeight() - nOffset); ++y)
+ {
+ tools::Long x1 = nOffset / 2;
+ tools::Long x2 = rRect.GetWidth() - nMidOffset - nOffset / std::max((nOffset - 3), 2);
+
+ rDevice.DrawPixel(Point(x1, y));
+ rDevice.DrawPixel(Point(x2, y));
+ }
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPixel::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPixelOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPixelOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPixel::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPixelOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPixelOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPixel::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPixelOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPixelOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/polygon.cxx b/vcl/backendtest/outputdevice/polygon.cxx
new file mode 100644
index 000000000..051c0d893
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polygon.cxx
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+namespace
+{
+void drawPolygonOffset(OutputDevice& rDevice, tools::Rectangle const& rRect, int nOffset,
+ int nFix = 0)
+{
+ // Note: According to https://lists.freedesktop.org/archives/libreoffice/2019-November/083709.html
+ // filling polygons always skips the right-most and bottom-most pixels, in order to avoid
+ // overlaps when drawing adjacent polygons. Specifying nFix = 1 allows to visually compensate
+ // for this by making the polygon explicitly larger.
+ tools::Polygon aPolygon(4);
+ int nMidOffset = rRect.GetWidth() / 2;
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset - (nOffset+1)/2, rRect.Top() + nOffset - 1), 0);
+ aPolygon.SetPoint(Point(rRect.Right() - nMidOffset + nFix - nOffset/3, rRect.Top() + nOffset - 1), 1);
+ aPolygon.SetPoint(Point(rRect.Right() - nMidOffset + nFix - nOffset/3, rRect.Bottom() - nOffset + nFix + 1), 2);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset - (nOffset+1)/2, rRect.Bottom() - nOffset + nFix + 1), 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ rDevice.DrawPolygon(aPolygon);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolygon::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupFilledRectangle(bool useLineColor)
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ if (useLineColor)
+ mpVirtualDevice->SetLineColor(constLineColor);
+ else
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(constFillColor);
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2, useLineColor ? 0 : 1);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupDiamond()
+{
+ initialSetup(11, 11, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aPoint1, aPoint2, aPoint3, aPoint4;
+ OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3,
+ aPoint4);
+
+ tools::Polygon aPolygon(4);
+
+ aPolygon.SetPoint(aPoint1, 0);
+ aPolygon.SetPoint(aPoint2, 1);
+ aPolygon.SetPoint(aPoint3, 2);
+ aPolygon.SetPoint(aPoint4, 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ mpVirtualDevice->DrawPolygon(aPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupLines()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aHorizontalLinePoint1, aHorizontalLinePoint2;
+ Point aVerticalLinePoint1, aVerticalLinePoint2;
+ Point aDiagonalLinePoint1, aDiagonalLinePoint2;
+
+ OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
+ maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2, aVerticalLinePoint1,
+ aVerticalLinePoint2, aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ tools::Polygon aHorizontalPolygon(2);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint1, 0);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint2, 1);
+ mpVirtualDevice->DrawPolygon(aHorizontalPolygon);
+
+ tools::Polygon aVerticalPolygon(2);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint1, 0);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint2, 1);
+ mpVirtualDevice->DrawPolygon(aVerticalPolygon);
+
+ tools::Polygon aDiagonalPolygon(2);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint1, 0);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint2, 1);
+ mpVirtualDevice->DrawPolygon(aDiagonalPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupAALines()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetAntialiasing(AntialiasingFlags::Enable);
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aHorizontalLinePoint1, aHorizontalLinePoint2;
+ Point aVerticalLinePoint1, aVerticalLinePoint2;
+ Point aDiagonalLinePoint1, aDiagonalLinePoint2;
+
+ OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
+ maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2, aVerticalLinePoint1,
+ aVerticalLinePoint2, aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ tools::Polygon aHorizontalPolygon(2);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint1, 0);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint2, 1);
+ mpVirtualDevice->DrawPolygon(aHorizontalPolygon);
+
+ tools::Polygon aVerticalPolygon(2);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint1, 0);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint2, 1);
+ mpVirtualDevice->DrawPolygon(aVerticalPolygon);
+
+ tools::Polygon aDiagonalPolygon(2);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint1, 0);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint2, 1);
+ mpVirtualDevice->DrawPolygon(aDiagonalPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupDropShape()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolygon(OutputDeviceTestCommon::createDropShapePolygon());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupAADropShape()
+{
+ initialSetup(21, 21, constBackgroundColor, true);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolygon(OutputDeviceTestCommon::createDropShapePolygon());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupHalfEllipse(bool aEnableAA)
+{
+ initialSetup(19, 21, constBackgroundColor, aEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(
+ tools::Polygon(OutputDeviceTestCommon::createHalfEllipsePolygon()));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupClosedBezier()
+{
+ initialSetup(21, 16, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createClosedBezierLoop(maVDRectangle));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupFilledAsymmetricalDropShape()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ mpVirtualDevice->DrawPolygon(OutputDeviceTestCommon::createDropShapePolygon());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupOpenPolygon()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolygon(tools::Polygon(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle)));
+ mpVirtualDevice->DrawPolygon(tools::Polygon(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle, 7)));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/polyline.cxx b/vcl/backendtest/outputdevice/polyline.cxx
new file mode 100644
index 000000000..d187d4add
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polyline.cxx
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+#include <cmath>
+#include <vector>
+
+namespace vcl::test {
+
+namespace
+{
+
+void drawPolyLineOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset)
+{
+ tools::Polygon aPolygon(4);
+ int nMidOffset = rRect.GetWidth() / 2;
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset - (nOffset+1)/2, rRect.Top() + nOffset - 1), 0);
+ aPolygon.SetPoint(Point(rRect.Right() - nMidOffset - nOffset/3, rRect.Top() + nOffset - 1), 1);
+ aPolygon.SetPoint(Point(rRect.Right() - nMidOffset - nOffset/3, rRect.Bottom() - nOffset + 1), 2);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset - (nOffset+1)/2, rRect.Bottom() - nOffset + 1), 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ rDevice.DrawPolygon(aPolygon);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolyLine::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupDiamond()
+{
+ initialSetup(11, 11, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aPoint1, aPoint2, aPoint3, aPoint4;
+ OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3, aPoint4);
+
+ tools::Polygon aPolygon(4);
+
+ aPolygon.SetPoint(aPoint1, 0);
+ aPolygon.SetPoint(aPoint2, 1);
+ aPolygon.SetPoint(aPoint3, 2);
+ aPolygon.SetPoint(aPoint4, 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ mpVirtualDevice->DrawPolyLine(aPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupLines()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aHorizontalLinePoint1, aHorizontalLinePoint2;
+ Point aVerticalLinePoint1, aVerticalLinePoint2;
+ Point aDiagonalLinePoint1, aDiagonalLinePoint2;
+
+ OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
+ maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2,
+ aVerticalLinePoint1, aVerticalLinePoint2,
+ aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ tools::Polygon aHorizontalPolygon(2);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint1, 0);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint2, 1);
+ mpVirtualDevice->DrawPolyLine(aHorizontalPolygon);
+
+ tools::Polygon aVerticalPolygon(2);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint1, 0);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint2, 1);
+ mpVirtualDevice->DrawPolyLine(aVerticalPolygon);
+
+ tools::Polygon aDiagonalPolygon(2);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint1, 0);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint2, 1);
+ mpVirtualDevice->DrawPolyLine(aDiagonalPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupAALines()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetAntialiasing(AntialiasingFlags::Enable);
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ Point aHorizontalLinePoint1, aHorizontalLinePoint2;
+ Point aVerticalLinePoint1, aVerticalLinePoint2;
+ Point aDiagonalLinePoint1, aDiagonalLinePoint2;
+
+ OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
+ maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2,
+ aVerticalLinePoint1, aVerticalLinePoint2,
+ aDiagonalLinePoint1, aDiagonalLinePoint2);
+
+ tools::Polygon aHorizontalPolygon(2);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint1, 0);
+ aHorizontalPolygon.SetPoint(aHorizontalLinePoint2, 1);
+ mpVirtualDevice->DrawPolyLine(aHorizontalPolygon);
+
+ tools::Polygon aVerticalPolygon(2);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint1, 0);
+ aVerticalPolygon.SetPoint(aVerticalLinePoint2, 1);
+ mpVirtualDevice->DrawPolyLine(aVerticalPolygon);
+
+ tools::Polygon aDiagonalPolygon(2);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint1, 0);
+ aDiagonalPolygon.SetPoint(aDiagonalLinePoint2, 1);
+ mpVirtualDevice->DrawPolyLine(aDiagonalPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupDropShape()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createDropShapePolygon());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupAADropShape()
+{
+ initialSetup(21, 21, constBackgroundColor,true);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createDropShapePolygon());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupHalfEllipse(bool aEnableAA)
+{
+ initialSetup(19, 21, constBackgroundColor, aEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(
+ tools::Polygon(OutputDeviceTestCommon::createHalfEllipsePolygon()));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupClosedBezier()
+{
+ initialSetup(21, 16, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createClosedBezierLoop(maVDRectangle));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupOpenPolygon()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(
+ tools::Polygon(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle)));
+ mpVirtualDevice->DrawPolyLine(
+ tools::Polygon(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle, 7)));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLine::setupOpenBezier()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(tools::Polygon(OutputDeviceTestCommon::createOpenBezier()));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/polyline_b2d.cxx b/vcl/backendtest/outputdevice/polyline_b2d.cxx
new file mode 100644
index 000000000..1fa603d1e
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polyline_b2d.cxx
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+#include <vcl/bitmapex.hxx>
+
+namespace vcl::test
+{
+namespace
+{
+void drawPolyLineOffset(OutputDevice& rDevice, tools::Rectangle const& rRect, int nOffset)
+{
+ int nMidOffset = rRect.GetWidth() / 2;
+ basegfx::B2DPolygon aPolygon{
+ basegfx::B2DPoint(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Top() + nOffset - 1),
+ basegfx::B2DPoint(rRect.Right() - nMidOffset - nOffset / 3, rRect.Top() + nOffset - 1),
+ basegfx::B2DPoint(rRect.Right() - nMidOffset - nOffset / 3, rRect.Bottom() - nOffset + 1),
+ basegfx::B2DPoint(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Bottom() - nOffset + 1),
+ };
+ aPolygon.setClosed(true);
+
+ rDevice.DrawPolyLine(aPolygon, 0.0); // draw hairline
+}
+
+void addDiamondPoints(tools::Rectangle rRect, int nOffset, basegfx::B2DPolygon& rPolygon)
+{
+ double midPointX = rRect.Left() + (rRect.Right() - rRect.Left()) / 2.0;
+ double midPointY = rRect.Top() + (rRect.Bottom() - rRect.Top()) / 2.0;
+
+ rPolygon.append({ midPointX, midPointY - nOffset });
+ rPolygon.append({ midPointX + nOffset, midPointY });
+ rPolygon.append({ midPointX, midPointY + nOffset });
+ rPolygon.append({ midPointX - nOffset, midPointY });
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolyLineB2D::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmapEx(maVDRectangle.TopLeft(), maVDRectangle.GetSize())
+ .GetBitmap();
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupDiamond()
+{
+ initialSetup(11, 11, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolygon aPolygon;
+ addDiamondPoints(maVDRectangle, 4, aPolygon);
+ aPolygon.setClosed(true);
+
+ mpVirtualDevice->DrawPolyLine(aPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupBezier()
+{
+ initialSetup(21, 21, constBackgroundColor, false);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolygon aPolygon;
+ addDiamondPoints(maVDRectangle, 8, aPolygon);
+ aPolygon.setClosed(true);
+
+ double minX = maVDRectangle.Left() + 4;
+ double maxX = maVDRectangle.Right() - 4;
+ double minY = maVDRectangle.Top() + 4;
+ double maxY = maVDRectangle.Bottom() - 4;
+
+ aPolygon.setControlPoints(0, { minX, minY }, { maxX, minY });
+ aPolygon.setControlPoints(1, { maxX, minY }, { maxX, maxY });
+ aPolygon.setControlPoints(2, { maxX, maxY }, { minX, maxY });
+ aPolygon.setControlPoints(3, { minX, maxY }, { minX, minY });
+
+ mpVirtualDevice->DrawPolyLine(aPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupAABezier()
+{
+ initialSetup(21, 21, constBackgroundColor, true);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolygon aPolygon;
+ addDiamondPoints(maVDRectangle, 8, aPolygon);
+ aPolygon.setClosed(true);
+
+ double minX = maVDRectangle.Left() + 4;
+ double maxX = maVDRectangle.Right() - 4;
+ double minY = maVDRectangle.Top() + 4;
+ double maxY = maVDRectangle.Bottom() - 4;
+
+ aPolygon.setControlPoints(0, { minX, minY }, { maxX, minY });
+ aPolygon.setControlPoints(1, { maxX, minY }, { maxX, maxY });
+ aPolygon.setControlPoints(2, { maxX, maxY }, { minX, maxY });
+ aPolygon.setControlPoints(3, { minX, maxY }, { minX, minY });
+
+ mpVirtualDevice->DrawPolyLine(aPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupHalfEllipse(bool aEnableAA)
+{
+ initialSetup(19, 21, constBackgroundColor, aEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createHalfEllipsePolygon());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupOpenPolygon()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle));
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle, 7));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyLineB2D::setupOpenBezier()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ mpVirtualDevice->DrawPolyLine(OutputDeviceTestCommon::createOpenBezier());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/polypolygon.cxx b/vcl/backendtest/outputdevice/polypolygon.cxx
new file mode 100644
index 000000000..e1abb2f90
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polypolygon.cxx
@@ -0,0 +1,212 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+namespace
+{
+tools::Polygon createPolygonOffset(tools::Rectangle const& rRect, int nOffset, int nFix = 0)
+{
+ // Note: According to https://lists.freedesktop.org/archives/libreoffice/2019-November/083709.html
+ // filling polygons always skips the right-most and bottom-most pixels, in order to avoid
+ // overlaps when drawing adjacent polygons. Specifying nFix = 1 allows to visually compensate
+ // for this by making the polygon explicitly larger.
+ tools::Polygon aPolygon(4);
+ int nMidOffset = rRect.GetWidth() / 2;
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Top() + nOffset - 1),
+ 0);
+ aPolygon.SetPoint(
+ Point(rRect.Right() - nMidOffset + nFix - nOffset / 3, rRect.Top() + nOffset - 1), 1);
+ aPolygon.SetPoint(
+ Point(rRect.Right() - nMidOffset + nFix - nOffset / 3, rRect.Bottom() - nOffset + nFix + 1),
+ 2);
+ aPolygon.SetPoint(
+ Point(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Bottom() - nOffset + nFix + 1), 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+ return aPolygon;
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolyPolygon::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::PolyPolygon aPolyPolygon(2);
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 5));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygon::setupFilledRectangle(bool useLineColor)
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ if (useLineColor)
+ mpVirtualDevice->SetLineColor(constLineColor);
+ else
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ tools::PolyPolygon aPolyPolygon(1);
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2, useLineColor ? 0 : 1));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygon::setupIntersectingRectangles()
+{
+ initialSetup(24, 24, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ tools::PolyPolygon aPolyPolygon(4);
+
+ int nOffset = 2, nFix = 1;
+ tools::Polygon aPolygon1(4), aPolygon2(4), aPolygon3(4), aPolygon4(4);
+
+ /*
+ The intersection between different rectangles has been
+ achieved by stacking them on top of each other and decreasing and
+ increasing the top and bottom offset accordingly to the rectangle
+ keeping the left and the right offset intact which in turn coalesced
+ them to each other helping in achieving multiple intersecting rectangles.
+ The desired color fill pattern is then achieved by setting the fill
+ color which in turn would fill the shape with the provided color
+ in accordance to the even-odd filling rule.
+ */
+
+ //Rect - 1
+ aPolygon1.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Top() + (nOffset - 1) + nFix),
+ 0);
+ aPolygon1.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset - 1) + nFix),
+ 1);
+ aPolygon1.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - (nOffset + 8) + nFix),
+ 2);
+ aPolygon1.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Bottom() - (nOffset + 8) + nFix),
+ 3);
+ aPolyPolygon.Insert(aPolygon1);
+
+ //Rect - 2
+ aPolygon2.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Top() + (nOffset + 2) + nFix),
+ 0);
+ aPolygon2.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset + 2) + nFix),
+ 1);
+ aPolygon2.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - (nOffset + 5) + nFix),
+ 2);
+ aPolygon2.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Bottom() - (nOffset + 5) + nFix),
+ 3);
+ aPolyPolygon.Insert(aPolygon2);
+
+ //Rect - 3
+ aPolygon3.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Top() + (nOffset + 5) + nFix),
+ 0);
+ aPolygon3.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset + 5) + nFix),
+ 1);
+ aPolygon3.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - (nOffset + 2) + nFix),
+ 2);
+ aPolygon3.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Bottom() - (nOffset + 2) + nFix),
+ 3);
+ aPolyPolygon.Insert(aPolygon3);
+
+ //Rect - 4
+ aPolygon4.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Top() + (nOffset + 8) + nFix),
+ 0);
+ aPolygon4.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset + 8) + nFix),
+ 1);
+ aPolygon4.SetPoint(Point(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - nOffset + nFix),
+ 2);
+ aPolygon4.SetPoint(
+ Point(maVDRectangle.Left() + nOffset + nFix, maVDRectangle.Bottom() - nOffset + nFix), 3);
+ aPolyPolygon.Insert(aPolygon4);
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygon::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::PolyPolygon aPolyPolygon(2);
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 5));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygon::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::PolyPolygon aPolyPolygon(2);
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 5));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygon::setupOpenPolygon()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::PolyPolygon aPolyPolygon;
+ aPolyPolygon.Insert(tools::Polygon(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle)));
+ aPolyPolygon.Insert(
+ tools::Polygon(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle, 7)));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/polypolygon_b2d.cxx b/vcl/backendtest/outputdevice/polypolygon_b2d.cxx
new file mode 100644
index 000000000..59391abe1
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polypolygon_b2d.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+namespace
+{
+basegfx::B2DPolygon createPolygonOffset(tools::Rectangle const& rRect, int nOffset, int nFix = 0)
+{
+ // Note: According to https://lists.freedesktop.org/archives/libreoffice/2019-November/083709.html
+ // filling polygons always skips the right-most and bottom-most pixels, in order to avoid
+ // overlaps when drawing adjacent polygons. Specifying nFix = 1 allows to visually compensate
+ // for this by making the polygon explicitly larger.
+ int nMidOffset = rRect.GetWidth() / 2;
+ basegfx::B2DPolygon aPolygon{
+ basegfx::B2DPoint(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Top() + nOffset - 1),
+ basegfx::B2DPoint(rRect.Right() - nMidOffset - nOffset / 3 + nFix,
+ rRect.Top() + nOffset - 1),
+ basegfx::B2DPoint(rRect.Right() - nMidOffset - nOffset / 3 + nFix,
+ rRect.Bottom() - nOffset + 1 + nFix),
+ basegfx::B2DPoint(rRect.Left() + nOffset - (nOffset + 1) / 2,
+ rRect.Bottom() - nOffset + 1 + nFix),
+ };
+ aPolygon.setClosed(true);
+ return aPolygon;
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolyPolygonB2D::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolyPolygon aPolyPolygon;
+ aPolyPolygon.append(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.append(createPolygonOffset(maVDRectangle, 5));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygonB2D::setupFilledRectangle(bool useLineColor)
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ if (useLineColor)
+ mpVirtualDevice->SetLineColor(constLineColor);
+ else
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ basegfx::B2DPolyPolygon aPolyPolygon(
+ createPolygonOffset(maVDRectangle, 2, useLineColor ? 0 : 1));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygonB2D::setupIntersectingRectangles()
+{
+ initialSetup(24, 24, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ int nOffset = 2, nFix = 1;
+ basegfx::B2DPolygon aPolygon1, aPolygon2, aPolygon3, aPolygon4;
+
+ /*
+ The intersection between different rectangles has been
+ achieved by stacking them on top of each other and decreasing and
+ increasing the top and bottom offset accordingly to the rectangle
+ keeping the left and the right offset intact which in turn coalesced
+ them to each other helping in achieving multiple intersecting rectangles.
+ The desired color fill pattern is then achieved by setting the fill
+ color which in turn would fill the shape with the provided color
+ in accordance to the even-odd filling rule.
+ */
+
+ //Rect - 1
+ aPolygon1.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Top() + (nOffset - 1) + nFix));
+ aPolygon1.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset - 1) + nFix));
+ aPolygon1.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - (nOffset + 8) + nFix));
+ aPolygon1.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Bottom() - (nOffset + 8) + nFix));
+ aPolygon1.setClosed(true);
+ aPolyPolygon.append(aPolygon1);
+
+ //Rect - 2
+ aPolygon2.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Top() + (nOffset + 2) + nFix));
+ aPolygon2.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset + 2) + nFix));
+ aPolygon2.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - (nOffset + 5) + nFix));
+ aPolygon2.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Bottom() - (nOffset + 5) + nFix));
+ aPolygon2.setClosed(true);
+ aPolyPolygon.append(aPolygon2);
+
+ //Rect - 3
+ aPolygon3.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Top() + (nOffset + 5) + nFix));
+ aPolygon3.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset + 5) + nFix));
+ aPolygon3.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - (nOffset + 2) + nFix));
+ aPolygon3.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Bottom() - (nOffset + 2) + nFix));
+ aPolygon3.setClosed(true);
+ aPolyPolygon.append(aPolygon3);
+
+ //Rect - 4
+ aPolygon4.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Top() + (nOffset + 8) + nFix));
+ aPolygon4.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Top() + (nOffset + 8) + nFix));
+ aPolygon4.append(basegfx::B2DPoint(maVDRectangle.Right() - (nOffset + 2) + nFix,
+ maVDRectangle.Bottom() - nOffset + nFix));
+ aPolygon4.append(basegfx::B2DPoint(maVDRectangle.Left() + nOffset + nFix,
+ maVDRectangle.Bottom() - nOffset + nFix));
+ aPolygon4.setClosed(true);
+ aPolyPolygon.append(aPolygon4);
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygonB2D::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolyPolygon aPolyPolygon;
+ aPolyPolygon.append(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.append(createPolygonOffset(maVDRectangle, 5));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygonB2D::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolyPolygon aPolyPolygon;
+ aPolyPolygon.append(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.append(createPolygonOffset(maVDRectangle, 5));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolyPolygonB2D::setupOpenPolygon()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ basegfx::B2DPolyPolygon aPolyPolygon;
+ aPolyPolygon.append(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle));
+ aPolyPolygon.append(OutputDeviceTestCommon::createOpenPolygon(maVDRectangle, 7));
+
+ mpVirtualDevice->DrawPolyPolygon(aPolyPolygon);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/rectangle.cxx b/vcl/backendtest/outputdevice/rectangle.cxx
new file mode 100644
index 000000000..f35285f28
--- /dev/null
+++ b/vcl/backendtest/outputdevice/rectangle.cxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+namespace
+{
+void drawRectOffset(OutputDevice& rDevice, tools::Rectangle const& rRect, int nOffset)
+{
+ int nMidOffset = rRect.Left() + (rRect.Right() - rRect.Left()) / 2;
+ rDevice.DrawRect(
+ tools::Rectangle(rRect.Left() + nOffset - (nOffset + 1) / 2, rRect.Top() + nOffset - 1,
+ rRect.Right() - nMidOffset - nOffset / 3, rRect.Bottom() - nOffset + 1));
+}
+
+void drawInvertOffset(OutputDevice& rDevice, tools::Rectangle const& rRect, int nOffset,
+ InvertFlags eFlags)
+{
+ tools::Rectangle aRectangle(rRect.Left() + nOffset, rRect.Top() + nOffset,
+ rRect.Right() - nOffset, rRect.Bottom() - nOffset);
+ rDevice.Invert(aRectangle, eFlags);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestRect::setupFilledRectangle(bool useLineColor)
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ if (useLineColor)
+ mpVirtualDevice->SetLineColor(constLineColor);
+ else
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 2);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupRectangle(bool bEnableAA)
+{
+ initialSetup(13, 13, constBackgroundColor, bEnableAA);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupInvert_NONE()
+{
+ initialSetup(20, 20, COL_WHITE);
+
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(COL_LIGHTRED);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 2), Size(8, 8)));
+ mpVirtualDevice->SetFillColor(COL_LIGHTGREEN);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(10, 2), Size(8, 8)));
+ mpVirtualDevice->SetFillColor(COL_LIGHTBLUE);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 10), Size(8, 8)));
+
+ drawInvertOffset(*mpVirtualDevice, maVDRectangle, 2, InvertFlags::NONE);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupInvert_N50()
+{
+ initialSetup(20, 20, COL_WHITE);
+
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(COL_LIGHTRED);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 2), Size(8, 8)));
+ mpVirtualDevice->SetFillColor(COL_LIGHTGREEN);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(10, 2), Size(8, 8)));
+ mpVirtualDevice->SetFillColor(COL_LIGHTBLUE);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 10), Size(8, 8)));
+
+ drawInvertOffset(*mpVirtualDevice, maVDRectangle, 2, InvertFlags::N50);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupInvert_TrackFrame()
+{
+ initialSetup(20, 20, COL_WHITE);
+
+ mpVirtualDevice->SetLineColor();
+ mpVirtualDevice->SetFillColor(COL_LIGHTRED);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 2), Size(8, 8)));
+ mpVirtualDevice->SetFillColor(COL_LIGHTGREEN);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(10, 2), Size(8, 8)));
+ mpVirtualDevice->SetFillColor(COL_LIGHTBLUE);
+ mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 10), Size(8, 8)));
+
+ drawInvertOffset(*mpVirtualDevice, maVDRectangle, 2, InvertFlags::TrackFrame);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupRectangleOnSize1028()
+{
+ initialSetup(1028, 1028, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupRectangleOnSize4096()
+{
+ initialSetup(4096, 4096, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+} // end namespace vcl::test
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/backendtest/outputdevice/text.cxx b/vcl/backendtest/outputdevice/text.cxx
new file mode 100644
index 000000000..5e53d900b
--- /dev/null
+++ b/vcl/backendtest/outputdevice/text.cxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: offset; indent-tabs-mode: nil; c-basic-offset: offset -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <test/outputdevice.hxx>
+
+namespace vcl::test
+{
+Bitmap OutputDeviceTestText::setupTextBitmap()
+{
+ initialSetup(21, 21, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ tools::Long midX = (maVDRectangle.Right() - maVDRectangle.Left()) / 2.0;
+ tools::Long midY = (maVDRectangle.Bottom() - maVDRectangle.Top()) / 2.0;
+
+ vcl::Font Font("DejaVu Sans", "Book", Size(0, 10));
+
+ mpVirtualDevice->Erase();
+ mpVirtualDevice->SetFont(Font);
+ mpVirtualDevice->SetTextColor(COL_LIGHTRED);
+ mpVirtualDevice->DrawText(Point(midX, midY - midY / 2), "I");
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+} \ No newline at end of file