1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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>
33 #include <test/outputdevice.hxx>
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
);
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
90 std::vector
<std::chrono::high_resolution_clock::time_point
> mTimePoints
;
91 static constexpr unsigned char gnNumberOfTests
= 6;
94 ScopedVclPtr
<VirtualDevice
> mpVDev
;
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
);
107 maUpdateTimer
.SetTimeout(1000.0);
108 maUpdateTimer
.Start();
112 virtual ~VisualBackendTestWindow() override
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
)
125 else if(nCode
== KEY_SPACE
)
128 if (nCode
== KEY_BACKSPACE
|| nCode
== KEY_SPACE
)
130 if (mnTest
% gnNumberOfTests
== gnNumberOfTests
- 1)
133 maUpdateTimer
.Start();
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);
162 static void testRectangles(vcl::RenderContext
& rRenderContext
, int nWidth
, int nHeight
)
164 tools::Rectangle aRectangle
;
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
;
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
;
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
;
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;
370 if (mTimePoints
.size() < constSamplesFPS
)
372 mTimePoints
.push_back(std::chrono::high_resolution_clock::now());
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
;
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
));
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(),
419 rRenderContext
.SetTextColor(COL_LIGHTRED
);
420 rRenderContext
.DrawText(Point(10, 10), "FPS: " + OUString::number(int(fps
)));
424 rRenderContext
.SetBackground(Wallpaper(COL_GREEN
));
426 Size aSize
= GetOutputSizePixel();
428 long nWidth
= aSize
.Width();
429 long nHeight
= aSize
.Height();
431 tools::Rectangle aRectangle
;
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)
488 maUpdateTimer
.SetTimeout(1000.0 / 60.0);
489 maUpdateTimer
.Start();
494 class VisualBackendTestApp
: public Application
498 VisualBackendTestApp()
501 virtual int Main() override
505 ScopedVclPtrInstance
<VisualBackendTestWindow
> aMainWindow
;
507 aMainWindow
->SetText("VCL Test");
510 Application::Execute();
512 catch (const css::uno::Exception
&)
514 DBG_UNHANDLED_EXCEPTION("vcl.app", "Fatal");
517 catch (const std::exception
& rException
)
519 SAL_WARN("vcl.app", "Fatal exception: " << rException
.what());
530 uno::Reference
<uno::XComponentContext
> xComponentContext
= ::cppu::defaultBootstrap_InitialComponentContext();
531 uno::Reference
<lang::XMultiServiceFactory
> xMSF(xComponentContext
->getServiceManager(), uno::UNO_QUERY
);
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: */