summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Repository.mk1
-rw-r--r--include/tools/gen.hxx8
-rw-r--r--vcl/Executable_visualbackendtest.mk58
-rw-r--r--vcl/Library_vcl.mk10
-rw-r--r--vcl/Module_vcl.mk1
-rw-r--r--vcl/backendtest/VisualBackendTest.cxx582
-rw-r--r--vcl/backendtest/outputdevice/bitmap.cxx154
-rw-r--r--vcl/backendtest/outputdevice/common.cxx328
-rw-r--r--vcl/backendtest/outputdevice/gradient.cxx43
-rw-r--r--vcl/backendtest/outputdevice/line.cxx114
-rw-r--r--vcl/backendtest/outputdevice/outputdevice.cxx75
-rw-r--r--vcl/backendtest/outputdevice/pixel.cxx57
-rw-r--r--vcl/backendtest/outputdevice/polygon.cxx151
-rw-r--r--vcl/backendtest/outputdevice/polyline.cxx140
-rw-r--r--vcl/backendtest/outputdevice/polypolygon.cxx68
-rw-r--r--vcl/backendtest/outputdevice/rectangle.cxx54
-rw-r--r--vcl/inc/test/outputdevice.hxx172
17 files changed, 2016 insertions, 0 deletions
diff --git a/Repository.mk b/Repository.mk
index 157fdd4031b4..03573fb27e32 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -74,6 +74,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
vcldemo \
tiledrendering \
mtfdemo \
+ visualbackendtest \
$(if $(and $(ENABLE_GTK3), $(filter LINUX %BSD SOLARIS,$(OS))), gtktiledviewer) \
))
diff --git a/include/tools/gen.hxx b/include/tools/gen.hxx
index cf8383f0ccbb..987dd4398bc3 100644
--- a/include/tools/gen.hxx
+++ b/include/tools/gen.hxx
@@ -379,6 +379,7 @@ public:
* Expands the rectangle in all directions by the input value.
*/
inline void expand(long nExpandBy);
+ inline void shrink(long nShrinkBy);
private:
long nLeft;
@@ -620,6 +621,13 @@ inline void Rectangle::expand(long nExpandBy)
nBottom += nExpandBy;
}
+inline void Rectangle::shrink(long nShrinkBy)
+{
+ nLeft += nShrinkBy;
+ nTop += nShrinkBy;
+ nRight -= nShrinkBy;
+ nBottom -= nShrinkBy;
+}
template< typename charT, typename traits >
inline std::basic_ostream<charT, traits> & operator <<(
diff --git a/vcl/Executable_visualbackendtest.mk b/vcl/Executable_visualbackendtest.mk
new file mode 100644
index 000000000000..abf8cbe1429b
--- /dev/null
+++ b/vcl/Executable_visualbackendtest.mk
@@ -0,0 +1,58 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+#
+# 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/.
+#
+
+$(eval $(call gb_Executable_Executable,visualbackendtest))
+
+$(eval $(call gb_Executable_use_api,visualbackendtest,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_Executable_use_external,visualbackendtest,boost_headers))
+
+$(eval $(call gb_Executable_set_include,visualbackendtest,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/vcl/inc \
+))
+
+$(eval $(call gb_Executable_use_libraries,visualbackendtest,\
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ tl \
+ sal \
+ salhelper \
+ vcl \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,visualbackendtest,\
+ vcl/backendtest/VisualBackendTest \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,visualbackendtest,\
+ vclmain \
+))
+
+ifeq ($(OS),LINUX)
+$(eval $(call gb_Executable_add_libs,visualbackendtest,\
+ -lm \
+ -ldl \
+ -lpthread \
+ -lGL \
+ -lX11 \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,visualbackendtest,\
+ glxtest \
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index b79087d85517..19a6f5285932 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -399,6 +399,16 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/uitest/uitest \
vcl/source/uitest/uno/uiobject_uno \
vcl/source/uitest/uno/uitest_uno \
+ vcl/backendtest/outputdevice/bitmap \
+ vcl/backendtest/outputdevice/common \
+ vcl/backendtest/outputdevice/gradient \
+ vcl/backendtest/outputdevice/line \
+ vcl/backendtest/outputdevice/outputdevice \
+ vcl/backendtest/outputdevice/pixel \
+ vcl/backendtest/outputdevice/polygon \
+ vcl/backendtest/outputdevice/polypolygon \
+ vcl/backendtest/outputdevice/polyline \
+ vcl/backendtest/outputdevice/rectangle \
))
$(eval $(call gb_Library_add_cobjects,vcl,\
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index ad08e5988a7b..19f9f7667cf7 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -35,6 +35,7 @@ $(eval $(call gb_Module_add_targets,vcl,\
$(if $(ENABLE_HEADLESS),, \
Executable_vcldemo \
Executable_icontest \
+ Executable_visualbackendtest \
Executable_mtfdemo ))) \
$(if $(filter-out ANDROID IOS WNT,$(OS)), \
Executable_svdemo \
diff --git a/vcl/backendtest/VisualBackendTest.cxx b/vcl/backendtest/VisualBackendTest.cxx
new file mode 100644
index 000000000000..7b6bc02fdd53
--- /dev/null
+++ b/vcl/backendtest/VisualBackendTest.cxx
@@ -0,0 +1,582 @@
+/* -*- 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 <rtl/math.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/random.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+#include <com/sun/star/ucb/UniversalContentBroker.hpp>
+
+#include <osl/time.h>
+#include <vcl/vclmain.hxx>
+#include <vcl/layout.hxx>
+#include <salhelper/thread.hxx>
+
+#include <tools/urlobj.hxx>
+#include <tools/stream.hxx>
+#include <tools/poly.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/pngread.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/button.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/pngwrite.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/salbtype.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/help.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <vcldemo-debug.hxx>
+
+#include <rtl/math.hxx>
+
+#include <chrono>
+#include <iostream>
+
+#include "test/outputdevice.hxx"
+
+using namespace css;
+
+void drawBitmapCentered(Rectangle& rRect, Bitmap aBitmap, vcl::RenderContext& rRenderContext)
+{
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+
+ Size aBitmapSize(aBitmap.GetSizePixel());
+
+ Point aPoint(rRect.TopLeft());
+
+ aPoint.X() += (nWidth - aBitmapSize.Width()) / 2;
+ aPoint.Y() += (nHeight - aBitmapSize.Height()) / 2;
+
+ rRenderContext.DrawBitmap(aPoint, aBitmap);
+}
+
+void drawBitmapScaledAndCentered(Rectangle& rRect, Bitmap aBitmap, vcl::RenderContext& rRenderContext, BmpScaleFlag aFlag = BmpScaleFlag::Fast)
+{
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+
+ Size aBitmapSize(aBitmap.GetSizePixel());
+
+ double fWidthHeight = nWidth > nHeight ? nHeight : nWidth;
+ double fScale = fWidthHeight / aBitmapSize.Width();
+ aBitmap.Scale(fScale, fScale, aFlag);
+
+ drawBitmapCentered(rRect, aBitmap, rRenderContext);
+}
+
+void drawBackgroundRect(Rectangle& rRect, Color aColor, vcl::RenderContext& rRenderContext)
+{
+ rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
+ rRenderContext.SetFillColor(aColor);
+ rRenderContext.SetLineColor(aColor);
+ rRenderContext.DrawRect(rRect);
+ rRenderContext.Pop();
+}
+
+void assertAndSetBackground(vcl::test::TestResult eResult, Rectangle& 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);
+}
+
+class VisualBackendTestWindow : public WorkWindow
+{
+private:
+ Timer maUpdateTimer;
+ std::vector<std::chrono::high_resolution_clock::time_point> mTimePoints;
+ unsigned char mnNumberOfTests;
+ unsigned char mnTest;
+ bool mbAnimate;
+ ScopedVclPtr<VirtualDevice> mpVDev;
+
+public:
+ VisualBackendTestWindow()
+ : WorkWindow(NULL, WB_APP | WB_STDWORK)
+ , mnNumberOfTests(6)
+ , mnTest(10 * mnNumberOfTests)
+ , mbAnimate(mnTest % mnNumberOfTests == mnNumberOfTests - 1)
+ , mpVDev(VclPtr<VirtualDevice>::Create())
+ {
+ maUpdateTimer.SetTimeoutHdl(LINK(this, VisualBackendTestWindow, updateHdl));
+ maUpdateTimer.SetPriority(SchedulerPriority::REPAINT);
+ if (mbAnimate)
+ {
+ maUpdateTimer.SetTimeout(1000.0);
+ maUpdateTimer.Start();
+ }
+ }
+
+ virtual ~VisualBackendTestWindow()
+ {
+ disposeOnce();
+ }
+
+ DECL_LINK_TYPED(updateHdl, Timer*, void);
+
+ virtual void dispose() override
+ {
+ WorkWindow::dispose();
+ }
+
+ 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)
+ {
+ if (mnTest % mnNumberOfTests == mnNumberOfTests - 1)
+ {
+ mbAnimate = true;
+ maUpdateTimer.Start();
+ }
+ else
+ {
+ mbAnimate = false;
+ Invalidate();
+ }
+ }
+ }
+
+ std::vector<Rectangle> setupRegions(int nPartitionsX, int nPartitionsY, int nWidth, int nHeight)
+ {
+ std::vector<Rectangle> aRegions;
+
+ for (int y = 0; y < nPartitionsY; y++)
+ {
+ for (int x = 0; x < nPartitionsX; x++)
+ {
+ long x1 = x * (nWidth / nPartitionsX);
+ long y1 = y * (nHeight / nPartitionsY);
+ long x2 = (x+1) * (nWidth / nPartitionsX);
+ long y2 = (y+1) * (nHeight / nPartitionsY);
+
+ aRegions.push_back(Rectangle(x1 + 1, y1 + 1, x2 - 2, y2 - 2));
+ }
+ }
+ return aRegions;
+ }
+
+ void testRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle();
+ assertAndSetBackground(aOutDevTest.checkRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPixel aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle();
+ assertAndSetBackground(aOutDevTest.checkRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle();
+ assertAndSetBackground(aOutDevTest.checkRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle();
+ assertAndSetBackground(aOutDevTest.checkRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle();
+ assertAndSetBackground(aOutDevTest.checkRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRectangle();
+ assertAndSetBackground(aOutDevTest.checkRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ void testFilledRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestRect aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle();
+ assertAndSetBackground(aOutDevTest.checkFilledRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle();
+ assertAndSetBackground(aOutDevTest.checkFilledRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupFilledRectangle();
+ assertAndSetBackground(aOutDevTest.checkFilledRectangle(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(aOutDevTest.checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(aOutDevTest.checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDiamond();
+ assertAndSetBackground(aOutDevTest.checkDiamond(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ void testLines(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLines();
+ assertAndSetBackground(aOutDevTest.checkLines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLines();
+ assertAndSetBackground(aOutDevTest.checkLines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLines();
+ assertAndSetBackground(aOutDevTest.checkLines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAALines();
+ assertAndSetBackground(aOutDevTest.checkAALines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolyLine aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAALines();
+ assertAndSetBackground(aOutDevTest.checkAALines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestPolygon aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupAALines();
+ assertAndSetBackground(aOutDevTest.checkAALines(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ void testBitmaps(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
+ {
+ Rectangle aRectangle;
+ size_t index = 0;
+
+ std::vector<Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmap();
+ assertAndSetBackground(aOutDevTest.checkTransformedBitmap(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap();
+ assertAndSetBackground(aOutDevTest.checkTransformedBitmap(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha();
+ assertAndSetBackground(aOutDevTest.checkBitmapExWithAlpha(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestBitmap aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawMask();
+ assertAndSetBackground(aOutDevTest.checkMask(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rRect*/) override
+ {
+ if (mnTest % mnNumberOfTests == mnNumberOfTests - 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::EnableB2dDraw | 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(a*M_PI / 180.0) * (b+1) * 20;
+ double y = std::cos(a*M_PI / 180.0) * (b+1) * 20;
+ polygon.append(basegfx::B2DPoint(x + 200 + 500 * fTime, y + 200 + 500 * fTime));
+ }
+ polygon.setClosed(true);
+ polyPolygon.append(polygon);
+ }
+
+ mpVDev->DrawPolyPolygon(polyPolygon);
+
+ 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.get());
+ rRenderContext.SetTextColor(COL_LIGHTRED);
+ rRenderContext.DrawText(Point(10, 10), OUString("FPS: ") + OUString::number(int(fps)));
+ return;
+ }
+
+ rRenderContext.SetBackground(Wallpaper(COL_GREEN));
+
+ Size aSize = GetOutputSizePixel();
+
+ long nWidth = aSize.Width();
+ long nHeight = aSize.Height();
+
+ Rectangle aRectangle;
+ size_t index = 0;
+
+ if (mnTest % mnNumberOfTests == 0)
+ {
+ testRectangles(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % mnNumberOfTests == 1)
+ {
+ testFilledRectangles(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % mnNumberOfTests == 2)
+ {
+ testLines(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % mnNumberOfTests == 3)
+ {
+ testBitmaps(rRenderContext, nWidth, nHeight);
+ }
+ else if (mnTest % mnNumberOfTests == 4)
+ {
+ std::vector<Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
+
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupDrawOutDev();
+ assertAndSetBackground(aOutDevTest.checkDrawOutDev(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupXOR();
+ assertAndSetBackground(aOutDevTest.checkXOR(aBitmap), aRectangle, rRenderContext);
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupLinearGradient();
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ aRectangle = aRegions[index++];
+ {
+ vcl::test::OutputDeviceTestGradient aOutDevTest;
+ Bitmap aBitmap = aOutDevTest.setupRadialGradient();
+ drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
+ }
+ }
+ }
+};
+
+IMPL_LINK_NOARG_TYPED(VisualBackendTestWindow, updateHdl, Timer *, void)
+{
+ if (mbAnimate)
+ {
+ maUpdateTimer.SetTimeout(1000.0 / 60.0);
+ maUpdateTimer.Start();
+ Invalidate();
+ }
+}
+
+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& rException)
+ {
+ SAL_WARN("vcl.app", "Fatal exception: " << rException.Message);
+ return 1;
+ }
+ catch (const std::exception& rException)
+ {
+ SAL_WARN("vcl.app", "Fatal exception: " << rException.what());
+ return 1;
+ }
+ return 0;
+ }
+
+protected:
+ uno::Reference<lang::XMultiServiceFactory> xMSF;
+
+ void Init() override
+ {
+ try
+ {
+ uno::Reference<uno::XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext();
+ xMSF = uno::Reference<lang::XMultiServiceFactory>(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
+ {
+ uno::Reference<lang::XComponent> xComponent(comphelper::getProcessComponentContext(), uno::UNO_QUERY_THROW);
+ xComponent->dispose();
+ 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 000000000000..351dfa2eb802
--- /dev/null
+++ b/vcl/backendtest/outputdevice/bitmap.cxx
@@ -0,0 +1,154 @@
+/* -*- 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>
+
+namespace vcl {
+namespace test {
+
+Bitmap OutputDeviceTestBitmap::setupDrawTransformedBitmap()
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, 24);
+ {
+ Bitmap::ScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(constFillColor);
+ aWriteAccess->SetLineColor(COL_YELLOW);
+ aWriteAccess->DrawRect(Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(Rectangle(2, 2, 6, 6));
+ }
+
+ 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::setupDrawBitmap()
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, 24);
+ {
+ Bitmap::ScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(constFillColor);
+ aWriteAccess->SetLineColor(COL_YELLOW);
+ aWriteAccess->DrawRect(Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(Rectangle(2, 2, 6, 6));
+ }
+
+ 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()
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, 24);
+ {
+ Bitmap::ScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(Color(0xFF, 0xFF, 0x00));
+ aWriteAccess->DrawRect(Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(Rectangle(3, 3, 5, 5));
+ }
+
+ AlphaMask aAlpha(aBitmapSize);
+ {
+ AlphaMask::ScopedWriteAccess aWriteAccess(aAlpha);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44));
+ aWriteAccess->DrawRect(Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(Rectangle(3, 3, 5, 5));
+ }
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ Point aPoint(alignToCenter(maVDRectangle, Rectangle(Point(), aBitmapSize)).TopLeft());
+
+ mpVirtualDevice->DrawBitmapEx(aPoint, BitmapEx(aBitmap, aAlpha));
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestBitmap::setupDrawMask()
+{
+ Size aBitmapSize(9, 9);
+ Bitmap aBitmap(aBitmapSize, 24);
+ {
+ Bitmap::ScopedWriteAccess aWriteAccess(aBitmap);
+ aWriteAccess->Erase(COL_WHITE);
+ aWriteAccess->SetLineColor(COL_BLACK);
+ aWriteAccess->DrawRect(Rectangle(0, 0, 8, 8));
+ aWriteAccess->DrawRect(Rectangle(3, 3, 5, 5));
+ }
+
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->DrawMask(Point(2, 2), aBitmap, constFillColor);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+TestResult OutputDeviceTestBitmap::checkBitmap(Bitmap& rBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor,
+ COL_YELLOW, constFillColor, COL_YELLOW, 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::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);
+}
+
+}} // 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 000000000000..ae3ef5963334
--- /dev/null
+++ b/vcl/backendtest/outputdevice/common.cxx
@@ -0,0 +1,328 @@
+/* -*- 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 {
+namespace 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(Bitmap::ScopedWriteAccess& pAccess, int x, int y, Color aExpected,
+ int& nNumberOfQuirks, int& nNumberOfErrors, bool bQuirkMode, int nColorDeltaThresh = 0)
+{
+ bool bColorize = false;
+ Color aColor = pAccess->GetPixel(y, x);
+ int nColorDelta = deltaColor(aColor, aExpected);
+
+ if (nColorDelta <= nColorDeltaThresh)
+ {
+ if (bColorize)
+ pAccess->SetPixel(y, x, Color(COL_LIGHTGREEN));
+ }
+ else if (bQuirkMode)
+ {
+ nNumberOfQuirks++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, Color(COL_YELLOW));
+ }
+ else
+ {
+ nNumberOfErrors++;
+ if (bColorize)
+ pAccess->SetPixel(y, x, Color(COL_LIGHTRED));
+ }
+}
+
+TestResult checkRect(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor)
+{
+ Bitmap::ScopedWriteAccess pAccess(rBitmap);
+ long nHeight = pAccess->Height();
+ long nWidth = pAccess->Width();
+
+ long firstX = 0 + aLayerNumber;
+ long firstY = 0 + aLayerNumber;
+
+ long lastX = nWidth - aLayerNumber - 1;
+ 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 (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 (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)
+{
+ Bitmap::ScopedWriteAccess pAccess(rBitmap);
+ long nWidth = pAccess->Width();
+ long nHeight = pAccess->Height();
+
+ TestResult aResult = TestResult::Passed;
+ int nNumberOfQuirks = 0;
+ int nNumberOfErrors = 0;
+
+ // check horizontal line
+ {
+ long startX = 4;
+ long endX = nWidth - 2;
+
+ long y = 1;
+
+ checkValue(pAccess, startX, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+ checkValue(pAccess, endX, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+
+ for (int x = startX + 1; x <= endX - 1; x++)
+ {
+ checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false, nColorThresh);
+ }
+ }
+
+ // check vertical line
+ {
+ long startY = 4;
+ long endY = nHeight - 2;
+
+ long x = 1;
+
+ checkValue(pAccess, x, startY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+ checkValue(pAccess, x, endY, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, true, nColorThresh);
+
+ for (int y = startY + 1; y <= endY - 1; y++)
+ {
+ checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false, nColorThresh);
+ }
+ }
+
+ // check diagonal line
+ {
+ long startX = 1;
+ long endX = nWidth - 2;
+
+ long startY = 1;
+ long endY = nHeight - 2;
+
+ long x = startX;
+ 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)
+{
+ Bitmap::ScopedWriteAccess pAccess(rBitmap);
+ long nHeight = pAccess->Height();
+ long nWidth = pAccess->Width();
+
+ long midX = nWidth / 2;
+ long midY = nHeight / 2;
+
+ long firstX = aLayerNumber;
+ long lastX = nWidth - aLayerNumber - 1;
+
+ long firstY = aLayerNumber;
+ long lastY = nHeight - aLayerNumber - 1;
+
+ 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 (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 (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_LIGHTBLUE);
+
+OutputDeviceTestCommon::OutputDeviceTestCommon()
+ : mpVirtualDevice(VclPtr<VirtualDevice>::Create())
+{}
+
+void OutputDeviceTestCommon::initialSetup(long nWidth, long nHeight, Color aColor)
+{
+ maVDRectangle = Rectangle(Point(), Size (nWidth, nHeight));
+ mpVirtualDevice->SetOutputSizePixel(maVDRectangle.GetSize());
+ 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
+}
+
+TestResult OutputDeviceTestCommon::checkRectangle(Bitmap& aBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor, constLineColor,
+ constBackgroundColor, constBackgroundColor, constLineColor, constBackgroundColor
+ };
+ return checkRectangles(aBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestCommon::checkFilledRectangle(Bitmap& aBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor,
+ constFillColor, constFillColor, constFillColor, constFillColor, constFillColor
+ };
+ return checkRectangles(aBitmap, aExpected);
+}
+
+TestResult OutputDeviceTestCommon::checkRectangles(Bitmap& aBitmap, std::vector<Color>& aExpectedColors)
+{
+ TestResult aReturnValue = TestResult::Passed;
+ for (size_t i = 0; i < aExpectedColors.size(); i++)
+ {
+ switch(checkRect(aBitmap, i, aExpectedColors[i]))
+ {
+ case TestResult::Failed:
+ return TestResult::Failed;
+ case TestResult::PassedWithQuirks:
+ aReturnValue = TestResult::PassedWithQuirks;
+ break;
+ default:
+ break;
+ }
+
+ }
+ return aReturnValue;
+}
+
+Rectangle OutputDeviceTestCommon::alignToCenter(Rectangle aRect1, Rectangle aRect2)
+{
+ Point aPoint((aRect1.GetWidth() / 2.0) - (aRect2.GetWidth() / 2.0),
+ (aRect1.GetHeight() / 2.0) - (aRect2.GetHeight() / 2.0));
+
+ return Rectangle(aPoint, aRect2.GetSize());
+}
+
+TestResult OutputDeviceTestCommon::checkDiamond(Bitmap& rBitmap)
+{
+ return checkDiamondLine(rBitmap, 1, constLineColor);
+}
+
+void OutputDeviceTestCommon::createDiamondPoints(Rectangle rRect, int nOffset,
+ Point& rPoint1, Point& rPoint2,
+ Point& rPoint3, Point& rPoint4)
+{
+ long midPointX = rRect.Left() + (rRect.Right() - rRect.Left()) / 2.0;
+ 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 );
+}
+
+void OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(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);
+}
+
+}} // 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 000000000000..f686e3270c80
--- /dev/null
+++ b/vcl/backendtest/outputdevice/gradient.cxx
@@ -0,0 +1,43 @@
+/* -*- 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 {
+namespace test {
+
+Bitmap OutputDeviceTestGradient::setupLinearGradient()
+{
+ initialSetup(12, 12, constBackgroundColor);
+
+ Gradient aGradient(GradientStyle_LINEAR, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00));
+ aGradient.SetAngle(900);
+ 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));
+ 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 000000000000..4cd39dbfcfe9
--- /dev/null
+++ b/vcl/backendtest/outputdevice/line.cxx
@@ -0,0 +1,114 @@
+/* -*- 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 {
+namespace test {
+
+namespace
+{
+
+void drawLineOffset(OutputDevice& rDevice, Rectangle& rRect, int nOffset)
+{
+ Point aLeftTop (rRect.Left() + nOffset, rRect.Top() + nOffset);
+ Point aRightTop (rRect.Right() - nOffset, rRect.Top() + nOffset);
+ Point aLeftBottom (rRect.Left() + nOffset, rRect.Bottom() - nOffset);
+ Point aRightBottom (rRect.Right() - nOffset, rRect.Bottom() - nOffset);
+
+ rDevice.DrawLine(aLeftTop, aRightTop);
+ rDevice.DrawLine(aRightTop, aRightBottom);
+ rDevice.DrawLine(aRightBottom, aLeftBottom);
+ rDevice.DrawLine(aLeftBottom, aLeftTop);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestLine::setupRectangle()
+{
+ initialSetup(13, 13, 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(constFillColor);
+ 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::EnableB2dDraw);
+ 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());
+}
+
+}} // 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 000000000000..6bc4278b8f65
--- /dev/null
+++ b/vcl/backendtest/outputdevice/outputdevice.cxx
@@ -0,0 +1,75 @@
+/* -*- 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 {
+namespace 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.get());
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestAnotherOutDev::setupXOR()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ Rectangle aDrawRectangle(maVDRectangle);
+ aDrawRectangle.shrink(2);
+
+ Rectangle aScissorRectangle(maVDRectangle);
+ aScissorRectangle.shrink(4);
+
+ mpVirtualDevice->SetRasterOp(ROP_XOR);
+ mpVirtualDevice->SetFillColor(constFillColor);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+
+ mpVirtualDevice->SetRasterOp(ROP_0);
+ mpVirtualDevice->SetFillColor(COL_BLACK);
+ mpVirtualDevice->DrawRect(aScissorRectangle);
+
+ mpVirtualDevice->SetRasterOp(ROP_XOR);
+ mpVirtualDevice->SetFillColor(constFillColor);
+ mpVirtualDevice->DrawRect(aDrawRectangle);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+TestResult OutputDeviceTestAnotherOutDev::checkDrawOutDev(Bitmap& rBitmap)
+{
+ return checkFilledRectangle(rBitmap);
+}
+
+TestResult OutputDeviceTestAnotherOutDev::checkXOR(Bitmap& rBitmap)
+{
+ std::vector<Color> aExpected
+ {
+ constBackgroundColor, constBackgroundColor,
+ constBackgroundColor, constBackgroundColor,
+ constFillColor, constFillColor,
+ constFillColor
+ };
+ return checkRectangles(rBitmap, aExpected);
+}
+
+}} // 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 000000000000..f13690e72209
--- /dev/null
+++ b/vcl/backendtest/outputdevice/pixel.cxx
@@ -0,0 +1,57 @@
+/* -*- 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 {
+namespace test {
+
+namespace
+{
+
+void drawPixelOffset(OutputDevice& rDevice, Rectangle& rRect, int nOffset)
+{
+ for (long x = 0 + nOffset; x < (rRect.GetWidth() - nOffset); ++x)
+ {
+ long y1 = nOffset;
+ long y2 = rRect.GetHeight() - nOffset - 1;
+
+ rDevice.DrawPixel(Point(x, y1));
+ rDevice.DrawPixel(Point(x, y2));
+ }
+
+ for (long y = 0 + nOffset; y < (rRect.GetHeight() - nOffset); ++y)
+ {
+ long x1 = nOffset;
+ long x2 = rRect.GetWidth() - nOffset - 1;
+
+ rDevice.DrawPixel(Point(x1, y));
+ rDevice.DrawPixel(Point(x2, y));
+ }
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPixel::setupRectangle()
+{
+ initialSetup(13, 13, 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 000000000000..de722c54abe9
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polygon.cxx
@@ -0,0 +1,151 @@
+/* -*- 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 {
+namespace test {
+
+namespace
+{
+
+void drawPolygonOffset(OutputDevice& rDevice, Rectangle& rRect, int nOffset)
+{
+ tools::Polygon aPolygon(4);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Top() + nOffset), 0);
+ aPolygon.SetPoint(Point(rRect.Right() - nOffset, rRect.Top() + nOffset), 1);
+ aPolygon.SetPoint(Point(rRect.Right() - nOffset, rRect.Bottom() - nOffset), 2);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Bottom() - nOffset), 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ rDevice.DrawPolygon(aPolygon);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolygon::setupRectangle()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constLineColor);
+ mpVirtualDevice->SetFillColor();
+
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestPolygon::setupFilledRectangle()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constFillColor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+ drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2);
+
+ 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::EnableB2dDraw);
+ 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());
+}
+
+}} // 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 000000000000..808d7274965b
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polyline.cxx
@@ -0,0 +1,140 @@
+/* -*- 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 {
+namespace test {
+
+namespace
+{
+
+void drawPolyLineOffset(OutputDevice& rDevice, Rectangle& rRect, int nOffset)
+{
+ tools::Polygon aPolygon(4);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Top() + nOffset), 0);
+ aPolygon.SetPoint(Point(rRect.Right() - nOffset, rRect.Top() + nOffset), 1);
+ aPolygon.SetPoint(Point(rRect.Right() - nOffset, rRect.Bottom() - nOffset), 2);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Bottom() - nOffset), 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+
+ rDevice.DrawPolyLine(aPolygon);
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolyLine::setupRectangle()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ 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::EnableB2dDraw);
+ 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());
+}
+
+}} // 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 000000000000..a6d3a018fbfc
--- /dev/null
+++ b/vcl/backendtest/outputdevice/polypolygon.cxx
@@ -0,0 +1,68 @@
+/* -*- 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 {
+namespace test {
+
+namespace
+{
+
+tools::Polygon createPolygonOffset(Rectangle& rRect, int nOffset)
+{
+ tools::Polygon aPolygon(4);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Top() + nOffset), 0);
+ aPolygon.SetPoint(Point(rRect.Right() - nOffset, rRect.Top() + nOffset), 1);
+ aPolygon.SetPoint(Point(rRect.Right() - nOffset, rRect.Bottom() - nOffset), 2);
+ aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Bottom() - nOffset), 3);
+ aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
+ return aPolygon;
+}
+
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestPolyPolygon::setupRectangle()
+{
+ initialSetup(13, 13, 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::setupFilledRectangle()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constFillColor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ tools::PolyPolygon aPolyPolygon(3);
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2));
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 4));
+ aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 4));
+
+ 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 000000000000..80ab3cf6f7ee
--- /dev/null
+++ b/vcl/backendtest/outputdevice/rectangle.cxx
@@ -0,0 +1,54 @@
+/* -*- 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 {
+namespace test {
+
+namespace
+{
+ void drawRectOffset(OutputDevice& rDevice, Rectangle& rRect, int nOffset)
+ {
+ rDevice.DrawRect(Rectangle(rRect.Left() + nOffset, rRect.Top() + nOffset,
+ rRect.Right() - nOffset, rRect.Bottom() - nOffset));
+
+ }
+} // end anonymous namespace
+
+Bitmap OutputDeviceTestRect::setupFilledRectangle()
+{
+ initialSetup(13, 13, constBackgroundColor);
+
+ mpVirtualDevice->SetLineColor(constFillColor);
+ mpVirtualDevice->SetFillColor(constFillColor);
+
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 2);
+ drawRectOffset(*mpVirtualDevice, maVDRectangle, 5);
+
+ return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
+}
+
+Bitmap OutputDeviceTestRect::setupRectangle()
+{
+ initialSetup(13, 13, 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/inc/test/outputdevice.hxx b/vcl/inc/test/outputdevice.hxx
new file mode 100644
index 000000000000..cc90b000b10d
--- /dev/null
+++ b/vcl/inc/test/outputdevice.hxx
@@ -0,0 +1,172 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_OUTDEVTESTS_HXX
+#define INCLUDED_VCL_OUTDEVTESTS_HXX
+
+#include <vcl/virdev.hxx>
+#include <vcl/bitmapaccess.hxx>
+
+namespace vcl {
+namespace test {
+
+/** Rendering test result.
+ *
+ * Test either "Passed", "Failed" or "PassedWithQuirks" which means
+ * the test passed but at least one rendering quirk was detected.
+ */
+enum class TestResult
+{
+ Failed,
+ PassedWithQuirks,
+ Passed
+};
+
+/** Common subclass for output device rendering tests.
+ */
+class VCL_DLLPUBLIC OutputDeviceTestCommon
+{
+protected:
+
+ ScopedVclPtr<VirtualDevice> mpVirtualDevice;
+ Rectangle maVDRectangle;
+
+ static const Color constBackgroundColor;
+ static const Color constLineColor;
+ static const Color constFillColor;
+
+public:
+ OutputDeviceTestCommon();
+
+ void initialSetup(long nWidth, long nHeight, Color aColor);
+
+ static TestResult checkRectangle(Bitmap& rBitmap);
+ static TestResult checkFilledRectangle(Bitmap& rBitmap);
+ static TestResult checkLines(Bitmap& rBitmap);
+ static TestResult checkAALines(Bitmap& rBitmap);
+ static TestResult checkDiamond(Bitmap& rBitmap);
+
+ static TestResult checkRectangles(Bitmap& rBitmap, std::vector<Color>& aExpectedColors);
+
+ static void createDiamondPoints(Rectangle rRect, int nOffset,
+ Point& rPoint1, Point& rPoint2,
+ Point& rPoint3, Point& rPoint4);
+
+ static void createHorizontalVerticalDiagonalLinePoints(Rectangle rRect,
+ Point& rHorizontalLinePoint1, Point& rHorizontalLinePoint2,
+ Point& rVerticalLinePoint1, Point& rVerticalLinePoint2,
+ Point& rDiagonalLinePoint1, Point& rDiagonalLinePoint2);
+ // tools
+ static Rectangle alignToCenter(Rectangle aRect1, Rectangle aRect2);
+
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestBitmap : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestBitmap() = default;
+
+ Bitmap setupDrawTransformedBitmap();
+ Bitmap setupDrawBitmap();
+ Bitmap setupDrawBitmapExWithAlpha();
+ Bitmap setupDrawMask();
+
+ static TestResult checkBitmap(Bitmap& rBitmap);
+ static TestResult checkTransformedBitmap(Bitmap& rBitmap);
+ static TestResult checkBitmapExWithAlpha(Bitmap& rBitmap);
+ static TestResult checkMask(Bitmap& rBitmap);
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestAnotherOutDev : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestAnotherOutDev() = default;
+
+ Bitmap setupDrawOutDev();
+ Bitmap setupXOR();
+
+ static TestResult checkDrawOutDev(Bitmap& rBitmap);
+ static TestResult checkXOR(Bitmap& rBitmap);
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestPixel : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestPixel() = default;
+
+ Bitmap setupRectangle();
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestLine : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestLine() = default;
+
+ Bitmap setupRectangle();
+ Bitmap setupDiamond();
+ Bitmap setupLines();
+ Bitmap setupAALines();
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestPolyLine : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestPolyLine() = default;
+
+ Bitmap setupRectangle();
+ Bitmap setupDiamond();
+ Bitmap setupLines();
+ Bitmap setupAALines();
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestRect : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestRect() = default;
+
+ Bitmap setupFilledRectangle();
+ Bitmap setupRectangle();
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestPolygon : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestPolygon() = default;
+
+ Bitmap setupFilledRectangle();
+ Bitmap setupRectangle();
+ Bitmap setupDiamond();
+ Bitmap setupLines();
+ Bitmap setupAALines();
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestPolyPolygon : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestPolyPolygon() = default;
+
+ Bitmap setupFilledRectangle();
+ Bitmap setupRectangle();
+};
+
+class VCL_DLLPUBLIC OutputDeviceTestGradient : public OutputDeviceTestCommon
+{
+public:
+ OutputDeviceTestGradient() = default;
+
+ Bitmap setupLinearGradient();
+ Bitmap setupRadialGradient();
+};
+
+}} // end namespace vcl::test
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */