Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / backendtest / VisualBackendTest.cxx
bloba3cfb8cb9ba180b965cfabd1f4a440774669ae30
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <math.h>
11 #include <sal/log.hxx>
13 #include <comphelper/processfactory.hxx>
14 #include <cppuhelper/bootstrap.hxx>
15 #include <com/sun/star/lang/XComponent.hpp>
16 #include <com/sun/star/uno/XComponentContext.hpp>
17 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
19 #include <vcl/event.hxx>
20 #include <vcl/gradient.hxx>
21 #include <vcl/vclmain.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/wrkwin.hxx>
25 #include <vcl/virdev.hxx>
27 #include <basegfx/numeric/ftools.hxx>
28 #include <tools/diagnose_ex.h>
30 #include <chrono>
31 #include <iostream>
33 #include <test/outputdevice.hxx>
35 using namespace css;
37 static void drawBitmapCentered(tools::Rectangle const& rRect, const Bitmap& aBitmap,
38 vcl::RenderContext& rRenderContext)
40 long nWidth = rRect.GetWidth();
41 long nHeight = rRect.GetHeight();
43 Size aBitmapSize(aBitmap.GetSizePixel());
45 Point aPoint(rRect.TopLeft());
47 aPoint.AdjustX((nWidth - aBitmapSize.Width()) / 2 );
48 aPoint.AdjustY((nHeight - aBitmapSize.Height()) / 2 );
50 rRenderContext.DrawBitmap(aPoint, aBitmap);
53 static void drawBitmapScaledAndCentered(tools::Rectangle const & rRect, Bitmap aBitmap, vcl::RenderContext& rRenderContext, BmpScaleFlag aFlag = BmpScaleFlag::Fast)
55 long nWidth = rRect.GetWidth();
56 long nHeight = rRect.GetHeight();
58 Size aBitmapSize(aBitmap.GetSizePixel());
60 double fWidthHeight = std::min(nWidth, nHeight);
61 double fScale = fWidthHeight / aBitmapSize.Width();
62 aBitmap.Scale(fScale, fScale, aFlag);
64 drawBitmapCentered(rRect, aBitmap, rRenderContext);
67 static void drawBackgroundRect(tools::Rectangle const & rRect, Color aColor, vcl::RenderContext& rRenderContext)
69 rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
70 rRenderContext.SetFillColor(aColor);
71 rRenderContext.SetLineColor(aColor);
72 rRenderContext.DrawRect(rRect);
73 rRenderContext.Pop();
76 static void assertAndSetBackground(vcl::test::TestResult eResult, tools::Rectangle const & rRect, vcl::RenderContext& rRenderContext)
78 if (eResult == vcl::test::TestResult::Passed)
79 drawBackgroundRect(rRect, COL_GREEN, rRenderContext);
80 else if (eResult == vcl::test::TestResult::PassedWithQuirks)
81 drawBackgroundRect(rRect, COL_YELLOW, rRenderContext);
82 else if (eResult == vcl::test::TestResult::Failed)
83 drawBackgroundRect(rRect, COL_RED, rRenderContext);
86 class VisualBackendTestWindow : public WorkWindow
88 private:
89 Timer maUpdateTimer;
90 std::vector<std::chrono::high_resolution_clock::time_point> mTimePoints;
91 static constexpr unsigned char gnNumberOfTests = 6;
92 unsigned char mnTest;
93 bool mbAnimate;
94 ScopedVclPtr<VirtualDevice> mpVDev;
96 public:
97 VisualBackendTestWindow()
98 : WorkWindow(nullptr, WB_APP | WB_STDWORK)
99 , mnTest(10 * gnNumberOfTests)
100 , mbAnimate(mnTest % gnNumberOfTests == gnNumberOfTests - 1)
101 , mpVDev(VclPtr<VirtualDevice>::Create())
103 maUpdateTimer.SetInvokeHandler(LINK(this, VisualBackendTestWindow, updateHdl));
104 maUpdateTimer.SetPriority(TaskPriority::REPAINT);
105 if (mbAnimate)
107 maUpdateTimer.SetTimeout(1000.0);
108 maUpdateTimer.Start();
112 virtual ~VisualBackendTestWindow() override
114 disposeOnce();
117 DECL_LINK(updateHdl, Timer*, void);
119 virtual void KeyInput(const KeyEvent& rKEvt) override
121 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
123 if (nCode == KEY_BACKSPACE)
124 mnTest--;
125 else if(nCode == KEY_SPACE)
126 mnTest++;
128 if (nCode == KEY_BACKSPACE || nCode == KEY_SPACE)
130 if (mnTest % gnNumberOfTests == gnNumberOfTests - 1)
132 mbAnimate = true;
133 maUpdateTimer.Start();
135 else
137 mbAnimate = false;
138 Invalidate();
143 static std::vector<tools::Rectangle> setupRegions(int nPartitionsX, int nPartitionsY, int nWidth, int nHeight)
145 std::vector<tools::Rectangle> aRegions;
147 for (int y = 0; y < nPartitionsY; y++)
149 for (int x = 0; x < nPartitionsX; x++)
151 long x1 = x * (nWidth / nPartitionsX);
152 long y1 = y * (nHeight / nPartitionsY);
153 long x2 = (x+1) * (nWidth / nPartitionsX);
154 long y2 = (y+1) * (nHeight / nPartitionsY);
156 aRegions.emplace_back(x1 + 1, y1 + 1, x2 - 2, y2 - 2);
159 return aRegions;
162 static void testRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
164 tools::Rectangle aRectangle;
165 size_t index = 0;
167 std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
169 aRectangle = aRegions[index++];
171 vcl::test::OutputDeviceTestRect aOutDevTest;
172 Bitmap aBitmap = aOutDevTest.setupRectangle(false);
173 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext);
174 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
177 aRectangle = aRegions[index++];
179 vcl::test::OutputDeviceTestPixel aOutDevTest;
180 Bitmap aBitmap = aOutDevTest.setupRectangle(false);
181 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext);
182 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
185 aRectangle = aRegions[index++];
187 vcl::test::OutputDeviceTestLine aOutDevTest;
188 Bitmap aBitmap = aOutDevTest.setupRectangle(false);
189 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext);
190 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
193 aRectangle = aRegions[index++];
195 vcl::test::OutputDeviceTestPolygon aOutDevTest;
196 Bitmap aBitmap = aOutDevTest.setupRectangle(false);
197 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext);
198 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
201 aRectangle = aRegions[index++];
203 vcl::test::OutputDeviceTestPolyLine aOutDevTest;
204 Bitmap aBitmap = aOutDevTest.setupRectangle(false);
205 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext);
206 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
209 aRectangle = aRegions[index++];
211 vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
212 Bitmap aBitmap = aOutDevTest.setupRectangle(false);
213 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext);
214 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
218 static void testFilledRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
220 tools::Rectangle aRectangle;
221 size_t index = 0;
223 std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
225 aRectangle = aRegions[index++];
227 vcl::test::OutputDeviceTestRect aOutDevTest;
228 Bitmap aBitmap = aOutDevTest.setupFilledRectangle();
229 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap), aRectangle, rRenderContext);
230 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
233 aRectangle = aRegions[index++];
235 vcl::test::OutputDeviceTestPolygon aOutDevTest;
236 Bitmap aBitmap = aOutDevTest.setupFilledRectangle();
237 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap), aRectangle, rRenderContext);
238 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
241 aRectangle = aRegions[index++];
243 vcl::test::OutputDeviceTestPolyPolygon aOutDevTest;
244 Bitmap aBitmap = aOutDevTest.setupFilledRectangle();
245 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap), aRectangle, rRenderContext);
246 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
249 aRectangle = aRegions[index++];
251 vcl::test::OutputDeviceTestPolygon aOutDevTest;
252 Bitmap aBitmap = aOutDevTest.setupDiamond();
253 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
254 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
256 aRectangle = aRegions[index++];
258 vcl::test::OutputDeviceTestLine aOutDevTest;
259 Bitmap aBitmap = aOutDevTest.setupDiamond();
260 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
261 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
263 aRectangle = aRegions[index++];
265 vcl::test::OutputDeviceTestPolyLine aOutDevTest;
266 Bitmap aBitmap = aOutDevTest.setupDiamond();
267 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext);
268 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
272 static void testLines(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
274 tools::Rectangle aRectangle;
275 size_t index = 0;
277 std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
279 aRectangle = aRegions[index++];
281 vcl::test::OutputDeviceTestLine aOutDevTest;
282 Bitmap aBitmap = aOutDevTest.setupLines();
283 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext);
284 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
286 aRectangle = aRegions[index++];
288 vcl::test::OutputDeviceTestPolyLine aOutDevTest;
289 Bitmap aBitmap = aOutDevTest.setupLines();
290 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext);
291 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
293 aRectangle = aRegions[index++];
295 vcl::test::OutputDeviceTestPolygon aOutDevTest;
296 Bitmap aBitmap = aOutDevTest.setupLines();
297 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext);
298 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
300 aRectangle = aRegions[index++];
302 vcl::test::OutputDeviceTestLine aOutDevTest;
303 Bitmap aBitmap = aOutDevTest.setupAALines();
304 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext);
305 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
307 aRectangle = aRegions[index++];
309 vcl::test::OutputDeviceTestPolyLine aOutDevTest;
310 Bitmap aBitmap = aOutDevTest.setupAALines();
311 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext);
312 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
314 aRectangle = aRegions[index++];
316 vcl::test::OutputDeviceTestPolygon aOutDevTest;
317 Bitmap aBitmap = aOutDevTest.setupAALines();
318 assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext);
319 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
323 static void testBitmaps(vcl::RenderContext& rRenderContext, int nWidth, int nHeight)
325 tools::Rectangle aRectangle;
326 size_t index = 0;
328 std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight);
330 aRectangle = aRegions[index++];
332 vcl::test::OutputDeviceTestBitmap aOutDevTest;
333 Bitmap aBitmap = aOutDevTest.setupDrawBitmap();
334 assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap), aRectangle, rRenderContext);
335 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
337 aRectangle = aRegions[index++];
339 vcl::test::OutputDeviceTestBitmap aOutDevTest;
340 Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap();
341 assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap), aRectangle, rRenderContext);
342 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
344 aRectangle = aRegions[index++];
346 vcl::test::OutputDeviceTestBitmap aOutDevTest;
347 Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha();
348 assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap), aRectangle, rRenderContext);
349 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
351 aRectangle = aRegions[index++];
353 vcl::test::OutputDeviceTestBitmap aOutDevTest;
354 Bitmap aBitmap = aOutDevTest.setupDrawMask();
355 assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap), aRectangle, rRenderContext);
356 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
360 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) override
362 if (mnTest % gnNumberOfTests == gnNumberOfTests - 1)
364 rRenderContext.SetBackground(Wallpaper(COL_GREEN));
366 static size_t nTimeIndex = 0;
367 static const size_t constSamplesFPS = 120;
368 double fps = 0.0;
370 if (mTimePoints.size() < constSamplesFPS)
372 mTimePoints.push_back(std::chrono::high_resolution_clock::now());
373 nTimeIndex++;
375 else
377 size_t current = nTimeIndex % constSamplesFPS;
378 mTimePoints[current] = std::chrono::high_resolution_clock::now();
379 size_t last = (nTimeIndex + 1) % constSamplesFPS;
380 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(mTimePoints[current] - mTimePoints[last]).count();
381 fps = constSamplesFPS * 1000.0 / ms;
382 nTimeIndex++;
385 double fTime = 0.5 + std::sin(nTimeIndex / 100.0) / 2.0;
387 Size aSizePixel = GetSizePixel();
389 mpVDev->SetAntialiasing(AntialiasingFlags::EnableB2dDraw | AntialiasingFlags::PixelSnapHairline);
390 mpVDev->SetOutputSizePixel(aSizePixel);
391 mpVDev->SetBackground(Wallpaper(COL_LIGHTGRAY));
392 mpVDev->Erase();
393 mpVDev->SetFillColor(COL_LIGHTRED);
394 mpVDev->SetLineColor(COL_LIGHTBLUE);
396 basegfx::B2DPolyPolygon polyPolygon;
398 for (int b=10; b<14; b++)
400 basegfx::B2DPolygon polygon;
401 for (double a=0.0; a<360.0; a+=0.5)
403 double x = std::sin(basegfx::deg2rad(a)) * (b+1) * 20;
404 double y = std::cos(basegfx::deg2rad(a)) * (b+1) * 20;
405 polygon.append(basegfx::B2DPoint(x + 200 + 500 * fTime, y + 200 + 500 * fTime));
407 polygon.setClosed(true);
408 polyPolygon.append(polygon);
411 mpVDev->DrawPolyPolygon(polyPolygon);
413 tools::Rectangle aGradientRect(Point(200, 200), Size(200 + fTime * 300, 200 + fTime * 300));
414 mpVDev->DrawGradient(aGradientRect, Gradient(GradientStyle::Linear, COL_YELLOW, COL_BLUE));
416 rRenderContext.DrawOutDev(Point(), mpVDev->GetOutputSizePixel(),
417 Point(), mpVDev->GetOutputSizePixel(),
418 *mpVDev);
419 rRenderContext.SetTextColor(COL_LIGHTRED);
420 rRenderContext.DrawText(Point(10, 10), "FPS: " + OUString::number(int(fps)));
421 return;
424 rRenderContext.SetBackground(Wallpaper(COL_GREEN));
426 Size aSize = GetOutputSizePixel();
428 long nWidth = aSize.Width();
429 long nHeight = aSize.Height();
431 tools::Rectangle aRectangle;
432 size_t index = 0;
434 if (mnTest % gnNumberOfTests == 0)
436 testRectangles(rRenderContext, nWidth, nHeight);
438 else if (mnTest % gnNumberOfTests == 1)
440 testFilledRectangles(rRenderContext, nWidth, nHeight);
442 else if (mnTest % gnNumberOfTests == 2)
444 testLines(rRenderContext, nWidth, nHeight);
446 else if (mnTest % gnNumberOfTests == 3)
448 testBitmaps(rRenderContext, nWidth, nHeight);
450 else if (mnTest % gnNumberOfTests == 4)
452 std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight);
454 aRectangle = aRegions[index++];
456 vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
457 Bitmap aBitmap = aOutDevTest.setupDrawOutDev();
458 assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDev(aBitmap), aRectangle, rRenderContext);
459 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
461 aRectangle = aRegions[index++];
463 vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest;
464 Bitmap aBitmap = aOutDevTest.setupXOR();
465 assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkXOR(aBitmap), aRectangle, rRenderContext);
466 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
468 aRectangle = aRegions[index++];
470 vcl::test::OutputDeviceTestGradient aOutDevTest;
471 Bitmap aBitmap = aOutDevTest.setupLinearGradient();
472 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
474 aRectangle = aRegions[index++];
476 vcl::test::OutputDeviceTestGradient aOutDevTest;
477 Bitmap aBitmap = aOutDevTest.setupRadialGradient();
478 drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext);
484 IMPL_LINK_NOARG(VisualBackendTestWindow, updateHdl, Timer *, void)
486 if (mbAnimate)
488 maUpdateTimer.SetTimeout(1000.0 / 60.0);
489 maUpdateTimer.Start();
490 Invalidate();
494 class VisualBackendTestApp : public Application
497 public:
498 VisualBackendTestApp()
501 virtual int Main() override
505 ScopedVclPtrInstance<VisualBackendTestWindow> aMainWindow;
507 aMainWindow->SetText("VCL Test");
508 aMainWindow->Show();
510 Application::Execute();
512 catch (const css::uno::Exception&)
514 DBG_UNHANDLED_EXCEPTION("vcl.app", "Fatal");
515 return 1;
517 catch (const std::exception& rException)
519 SAL_WARN("vcl.app", "Fatal exception: " << rException.what());
520 return 1;
522 return 0;
525 protected:
526 void Init() override
530 uno::Reference<uno::XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext();
531 uno::Reference<lang::XMultiServiceFactory> xMSF(xComponentContext->getServiceManager(), uno::UNO_QUERY);
533 if (!xMSF.is())
534 Application::Abort("Bootstrap failure - no service manager");
536 comphelper::setProcessServiceFactory(xMSF);
538 catch (const uno::Exception &e)
540 Application::Abort("Bootstrap exception " + e.Message);
544 void DeInit() override
546 uno::Reference<lang::XComponent> xComponent(comphelper::getProcessComponentContext(), uno::UNO_QUERY_THROW);
547 xComponent->dispose();
548 comphelper::setProcessServiceFactory(nullptr);
552 void vclmain::createApplication()
554 static VisualBackendTestApp aApplication;
557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */