diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /vcl/backendtest | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/backendtest')
-rw-r--r-- | vcl/backendtest/VisualBackendTest.cxx | 690 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/bitmap.cxx | 193 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/clip.cxx | 83 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/common.cxx | 478 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/gradient.cxx | 43 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/line.cxx | 200 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/outputdevice.cxx | 95 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/pixel.cxx | 56 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/polygon.cxx | 157 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/polyline.cxx | 139 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/polyline_b2d.cxx | 127 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/polypolygon.cxx | 72 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/polypolygon_b2d.cxx | 70 | ||||
-rw-r--r-- | vcl/backendtest/outputdevice/rectangle.cxx | 114 |
14 files changed, 2517 insertions, 0 deletions
diff --git a/vcl/backendtest/VisualBackendTest.cxx b/vcl/backendtest/VisualBackendTest.cxx new file mode 100644 index 000000000..08efc1d38 --- /dev/null +++ b/vcl/backendtest/VisualBackendTest.cxx @@ -0,0 +1,690 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <math.h> +#include <sal/log.hxx> + +#include <comphelper/processfactory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <vcl/event.hxx> +#include <vcl/gradient.hxx> +#include <vcl/vclmain.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/virdev.hxx> + +#include <basegfx/numeric/ftools.hxx> +#include <tools/diagnose_ex.h> + +#include <chrono> +#include <iostream> + +#include <test/outputdevice.hxx> + +using namespace css; + +static void drawBitmapCentered(tools::Rectangle const& rRect, const Bitmap& aBitmap, + vcl::RenderContext& rRenderContext) +{ + long nWidth = rRect.GetWidth(); + long nHeight = rRect.GetHeight(); + + Size aBitmapSize(aBitmap.GetSizePixel()); + + Point aPoint(rRect.TopLeft()); + + aPoint.AdjustX((nWidth - aBitmapSize.Width()) / 2 ); + aPoint.AdjustY((nHeight - aBitmapSize.Height()) / 2 ); + + rRenderContext.DrawBitmap(aPoint, aBitmap); +} + +static void drawBitmapScaledAndCentered(tools::Rectangle const & rRect, Bitmap aBitmap, vcl::RenderContext& rRenderContext, BmpScaleFlag aFlag = BmpScaleFlag::Fast) +{ + long nWidth = rRect.GetWidth(); + long nHeight = rRect.GetHeight(); + + Size aBitmapSize(aBitmap.GetSizePixel()); + + double fWidthHeight = std::min(nWidth, nHeight); + double fScale = fWidthHeight / aBitmapSize.Width(); + aBitmap.Scale(fScale, fScale, aFlag); + + drawBitmapCentered(rRect, aBitmap, rRenderContext); +} + +static void drawBackgroundRect(tools::Rectangle const & rRect, Color aColor, vcl::RenderContext& rRenderContext) +{ + rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR); + rRenderContext.SetFillColor(aColor); + rRenderContext.SetLineColor(aColor); + rRenderContext.DrawRect(rRect); + rRenderContext.Pop(); +} + +static void assertAndSetBackground(vcl::test::TestResult eResult, tools::Rectangle const & rRect, vcl::RenderContext& rRenderContext) +{ + if (eResult == vcl::test::TestResult::Passed) + drawBackgroundRect(rRect, COL_GREEN, rRenderContext); + else if (eResult == vcl::test::TestResult::PassedWithQuirks) + drawBackgroundRect(rRect, COL_YELLOW, rRenderContext); + else if (eResult == vcl::test::TestResult::Failed) + drawBackgroundRect(rRect, COL_RED, rRenderContext); +} + +namespace { + +class VisualBackendTestWindow : public WorkWindow +{ +private: + Timer maUpdateTimer; + std::vector<std::chrono::high_resolution_clock::time_point> mTimePoints; + static constexpr unsigned char gnNumberOfTests = 9; + unsigned char mnTest; + bool mbAnimate; + ScopedVclPtr<VirtualDevice> mpVDev; + +public: + VisualBackendTestWindow() + : WorkWindow(nullptr, WB_APP | WB_STDWORK) + , mnTest(10 * gnNumberOfTests) + , mbAnimate(mnTest % gnNumberOfTests == gnNumberOfTests - 1) + , mpVDev(VclPtr<VirtualDevice>::Create()) + { + maUpdateTimer.SetInvokeHandler(LINK(this, VisualBackendTestWindow, updateHdl)); + maUpdateTimer.SetPriority(TaskPriority::DEFAULT_IDLE); + if (mbAnimate) + { + maUpdateTimer.SetTimeout(1000.0); + maUpdateTimer.Start(); + } + } + + virtual ~VisualBackendTestWindow() override + { + disposeOnce(); + } + + DECL_LINK(updateHdl, Timer*, void); + + virtual void KeyInput(const KeyEvent& rKEvt) override + { + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + + if (nCode == KEY_BACKSPACE) + mnTest--; + else if(nCode == KEY_SPACE) + mnTest++; + + if (nCode == KEY_BACKSPACE || nCode == KEY_SPACE) + { + if (mnTest % gnNumberOfTests == gnNumberOfTests - 1) + { + mbAnimate = true; + maUpdateTimer.Start(); + } + else + { + mbAnimate = false; + Invalidate(); + } + } + } + + static std::vector<tools::Rectangle> setupRegions(int nPartitionsX, int nPartitionsY, int nWidth, int nHeight) + { + std::vector<tools::Rectangle> aRegions; + + for (int y = 0; y < nPartitionsY; y++) + { + for (int x = 0; x < nPartitionsX; x++) + { + long x1 = x * (nWidth / nPartitionsX); + long y1 = y * (nHeight / nPartitionsY); + long x2 = (x+1) * (nWidth / nPartitionsX); + long y2 = (y+1) * (nHeight / nPartitionsY); + + aRegions.emplace_back(x1 + 1, y1 + 1, x2 - 2, y2 - 2); + } + } + return aRegions; + } + + static void testRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestRect aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPixel aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + } + + static void testFilledRectangles(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestRect aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupFilledRectangle(false); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, false), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestRect aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupFilledRectangle(true); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkFilledRectangle(aBitmap, true), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + } + + static void testDiamonds(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(3, 1, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDiamond(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDiamond(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDiamond(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkDiamond(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + } + + static void testLines(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupLines(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupLines(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupLines(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkLines(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupAALines(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolyLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupAALines(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestPolygon aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupAALines(); + assertAndSetBackground(vcl::test::OutputDeviceTestCommon::checkAALines(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + } + + static void testBitmaps(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(3, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestBitmap aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDrawBitmap(); + assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestBitmap aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDrawTransformedBitmap(); + assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkTransformedBitmap(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestBitmap aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDrawBitmapExWithAlpha(); + assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkBitmapExWithAlpha(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestBitmap aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDrawMask(); + assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkMask(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestBitmap aOutDevTest; + BitmapEx aBitmap = aOutDevTest.setupDrawBlend(); + assertAndSetBackground(vcl::test::OutputDeviceTestBitmap::checkBlend(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap.GetBitmap(), rRenderContext); + } + } + + static void testInvert(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestRect aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupInvert_NONE(); + assertAndSetBackground(vcl::test::OutputDeviceTestRect::checkInvertRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestRect aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupInvert_N50(); + assertAndSetBackground(vcl::test::OutputDeviceTestRect::checkInvertN50Rectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestRect aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupInvert_TrackFrame(); + assertAndSetBackground(vcl::test::OutputDeviceTestRect::checkInvertTrackFrameRectangle(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupXOR(); + assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkXOR(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + } + + static void testClip(vcl::RenderContext& rRenderContext, int nWidth, int nHeight) + { + tools::Rectangle aRectangle; + size_t index = 0; + + std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestClip aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupClipRectangle(); + assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestClip aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupClipPolygon(); + assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestClip aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupClipPolyPolygon(); + assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestClip aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupClipB2DPolyPolygon(); + assertAndSetBackground(vcl::test::OutputDeviceTestClip::checkClip(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + } + + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) override + { + if (mnTest % gnNumberOfTests == gnNumberOfTests - 1) + { + rRenderContext.SetBackground(Wallpaper(COL_GREEN)); + + static size_t nTimeIndex = 0; + static const size_t constSamplesFPS = 120; + double fps = 0.0; + + if (mTimePoints.size() < constSamplesFPS) + { + mTimePoints.push_back(std::chrono::high_resolution_clock::now()); + nTimeIndex++; + } + else + { + size_t current = nTimeIndex % constSamplesFPS; + mTimePoints[current] = std::chrono::high_resolution_clock::now(); + size_t last = (nTimeIndex + 1) % constSamplesFPS; + auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(mTimePoints[current] - mTimePoints[last]).count(); + fps = constSamplesFPS * 1000.0 / ms; + nTimeIndex++; + } + + double fTime = 0.5 + std::sin(nTimeIndex / 100.0) / 2.0; + + Size aSizePixel = GetSizePixel(); + + mpVDev->SetAntialiasing(AntialiasingFlags::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(basegfx::deg2rad(a)) * (b+1) * 20; + double y = std::cos(basegfx::deg2rad(a)) * (b+1) * 20; + polygon.append(basegfx::B2DPoint(x + 200 + 500 * fTime, y + 200 + 500 * fTime)); + } + polygon.setClosed(true); + polyPolygon.append(polygon); + } + + mpVDev->DrawPolyPolygon(polyPolygon); + + tools::Rectangle aGradientRect(Point(200, 200), Size(200 + fTime * 300, 200 + fTime * 300)); + mpVDev->DrawGradient(aGradientRect, Gradient(GradientStyle::Linear, COL_YELLOW, COL_BLUE)); + + rRenderContext.DrawOutDev(Point(), mpVDev->GetOutputSizePixel(), + Point(), mpVDev->GetOutputSizePixel(), + *mpVDev); + rRenderContext.SetTextColor(COL_LIGHTRED); + rRenderContext.DrawText(Point(10, 10), "FPS: " + OUString::number(int(fps))); + return; + } + + rRenderContext.SetBackground(Wallpaper(COL_GREEN)); + + Size aSize = GetOutputSizePixel(); + + long nWidth = aSize.Width(); + long nHeight = aSize.Height(); + + tools::Rectangle aRectangle; + size_t index = 0; + + if (mnTest % gnNumberOfTests == 0) + { + testRectangles(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 1) + { + testFilledRectangles(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 2) + { + testDiamonds(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 3) + { + testLines(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 4) + { + testBitmaps(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 5) + { + testInvert(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 6) + { + testClip(rRenderContext, nWidth, nHeight); + } + else if (mnTest % gnNumberOfTests == 7) + { + std::vector<tools::Rectangle> aRegions = setupRegions(2, 2, nWidth, nHeight); + + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestAnotherOutDev aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDrawOutDev(); + assertAndSetBackground(vcl::test::OutputDeviceTestAnotherOutDev::checkDrawOutDev(aBitmap), aRectangle, rRenderContext); + drawBitmapScaledAndCentered(aRectangle, aBitmap, rRenderContext); + } + aRectangle = aRegions[index++]; + { + vcl::test::OutputDeviceTestLine aOutDevTest; + Bitmap aBitmap = aOutDevTest.setupDashedLine(); + assertAndSetBackground(vcl::test::OutputDeviceTestLine::checkDashedLine(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(VisualBackendTestWindow, updateHdl, Timer *, void) +{ + if (mbAnimate) + { + maUpdateTimer.SetTimeout(1.0); + maUpdateTimer.Start(); + Invalidate(); + } +} + +namespace { + +class VisualBackendTestApp : public Application +{ + +public: + VisualBackendTestApp() + {} + + virtual int Main() override + { + try + { + ScopedVclPtrInstance<VisualBackendTestWindow> aMainWindow; + + aMainWindow->SetText("VCL Test"); + aMainWindow->Show(); + + Application::Execute(); + } + catch (const css::uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("vcl.app", "Fatal"); + return 1; + } + catch (const std::exception& rException) + { + SAL_WARN("vcl.app", "Fatal exception: " << rException.what()); + return 1; + } + return 0; + } + +protected: + void Init() override + { + try + { + uno::Reference<uno::XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); + uno::Reference<lang::XMultiServiceFactory> xMSF(xComponentContext->getServiceManager(), uno::UNO_QUERY); + + if (!xMSF.is()) + Application::Abort("Bootstrap failure - no service manager"); + + comphelper::setProcessServiceFactory(xMSF); + } + catch (const uno::Exception &e) + { + Application::Abort("Bootstrap exception " + e.Message); + } + } + + void DeInit() override + { + 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 000000000..79cd3d379 --- /dev/null +++ b/vcl/backendtest/outputdevice/bitmap.cxx @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> +#include <vcl/bitmapex.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <bitmapwriteaccess.hxx> + +namespace vcl::test { + +Bitmap OutputDeviceTestBitmap::setupDrawTransformedBitmap() +{ + Size aBitmapSize(9, 9); + Bitmap aBitmap(aBitmapSize, 24); + { + BitmapScopedWriteAccess aWriteAccess(aBitmap); + aWriteAccess->Erase(constFillColor); + aWriteAccess->SetLineColor(COL_YELLOW); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(2, 2, 6, 6)); + } + + 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); + { + BitmapScopedWriteAccess aWriteAccess(aBitmap); + aWriteAccess->Erase(constFillColor); + aWriteAccess->SetLineColor(COL_YELLOW); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(2, 2, 6, 6)); + } + + 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); + { + BitmapScopedWriteAccess aWriteAccess(aBitmap); + aWriteAccess->Erase(COL_WHITE); + aWriteAccess->SetLineColor(Color(0xFF, 0xFF, 0x00)); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5)); + } + + AlphaMask aAlpha(aBitmapSize); + { + AlphaScopedWriteAccess aWriteAccess(aAlpha); + aWriteAccess->Erase(COL_WHITE); + aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44)); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5)); + } + + initialSetup(13, 13, constBackgroundColor); + + Point aPoint(alignToCenter(maVDRectangle, tools::Rectangle(Point(), aBitmapSize)).TopLeft()); + + mpVirtualDevice->DrawBitmapEx(aPoint, BitmapEx(aBitmap, aAlpha)); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestBitmap::setupDrawMask() +{ + Size aBitmapSize(9, 9); + Bitmap aBitmap(aBitmapSize, 24); + { + BitmapScopedWriteAccess aWriteAccess(aBitmap); + aWriteAccess->Erase(COL_WHITE); + aWriteAccess->SetLineColor(COL_BLACK); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5)); + } + + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->DrawMask(Point(2, 2), aBitmap, constLineColor); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +BitmapEx OutputDeviceTestBitmap::setupDrawBlend() +{ + Size aBitmapSize(9, 9); + Bitmap aBitmap(aBitmapSize, 24); + { + BitmapScopedWriteAccess aWriteAccess(aBitmap); + aWriteAccess->Erase(COL_WHITE); + aWriteAccess->SetLineColor(Color(0xFF, 0xFF, 0x00)); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5)); + } + + AlphaMask aAlpha(aBitmapSize); + { + AlphaScopedWriteAccess aWriteAccess(aAlpha); + aWriteAccess->Erase(COL_WHITE); + aWriteAccess->SetLineColor(Color(0x44, 0x44, 0x44)); + aWriteAccess->DrawRect(tools::Rectangle(0, 0, 8, 8)); + aWriteAccess->DrawRect(tools::Rectangle(3, 3, 5, 5)); + } + + initialSetup(13, 13, COL_TRANSPARENT, false, true); + mpVirtualDevice->SetFillColor(constBackgroundColor); + mpVirtualDevice->SetLineColor(constBackgroundColor); + // Leave the outer part of the device transparent, the inner part set to the background color. + // This will test blending of VirtualDevice's "alpha" device (outer yellow rectangle + // will be blended with transparent background, inner with the grey one). + mpVirtualDevice->DrawRect( tools::Rectangle( Point( 3, 3 ), Size( 7, 7 ))); + + Point aPoint(alignToCenter(maVDRectangle, tools::Rectangle(Point(), aBitmapSize)).TopLeft()); + + mpVirtualDevice->DrawBitmapEx(aPoint, BitmapEx(aBitmap, aAlpha)); + + return mpVirtualDevice->GetBitmapEx(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +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); +} + +TestResult OutputDeviceTestBitmap::checkBlend(BitmapEx& rBitmapEx) +{ + const Color aBlendedColor(0xEE, 0xEE, 0x33); + + std::vector<Color> aExpected + { + COL_WHITE, COL_WHITE, COL_YELLOW, constBackgroundColor, + constBackgroundColor, aBlendedColor, constBackgroundColor + }; + Bitmap aBitmap(rBitmapEx.GetBitmap()); + return checkRectangles(aBitmap, aExpected); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/clip.cxx b/vcl/backendtest/outputdevice/clip.cxx new file mode 100644 index 000000000..86064b583 --- /dev/null +++ b/vcl/backendtest/outputdevice/clip.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +namespace vcl::test +{ +Bitmap OutputDeviceTestClip::setupClipRectangle() +{ + initialSetup(13, 13, constBackgroundColor); + + tools::Rectangle rectangle = maVDRectangle; + rectangle.shrink(2); + mpVirtualDevice->SetClipRegion(vcl::Region(rectangle)); + mpVirtualDevice->SetBackground(constFillColor); + mpVirtualDevice->Erase(maVDRectangle); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestClip::setupClipPolygon() +{ + initialSetup(13, 13, constBackgroundColor); + + tools::Rectangle rectangle = maVDRectangle; + rectangle.shrink(2); + mpVirtualDevice->SetClipRegion(vcl::Region(tools::Polygon(rectangle))); + mpVirtualDevice->SetBackground(constFillColor); + mpVirtualDevice->Erase(maVDRectangle); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestClip::setupClipPolyPolygon() +{ + initialSetup(13, 13, constBackgroundColor); + + tools::Rectangle rectangle = maVDRectangle; + rectangle.shrink(2); + mpVirtualDevice->SetClipRegion(vcl::Region(tools::PolyPolygon(rectangle))); + mpVirtualDevice->SetBackground(constFillColor); + mpVirtualDevice->Erase(maVDRectangle); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestClip::setupClipB2DPolyPolygon() +{ + initialSetup(13, 13, constBackgroundColor); + + tools::Rectangle rectangle = maVDRectangle; + rectangle.shrink(2); + mpVirtualDevice->SetClipRegion(vcl::Region(basegfx::B2DPolyPolygon(basegfx::B2DPolygon{ + basegfx::B2DPoint(rectangle.getX(), rectangle.getY()), + basegfx::B2DPoint(rectangle.getX(), rectangle.getY() + rectangle.getHeight()), + basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(), + rectangle.getY() + rectangle.getHeight()), + basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(), rectangle.getY()), + }))); + mpVirtualDevice->SetBackground(constFillColor); + mpVirtualDevice->Erase(maVDRectangle); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +TestResult OutputDeviceTestClip::checkClip(Bitmap& aBitmap) +{ + std::vector<Color> aExpected{ constBackgroundColor, constBackgroundColor, constFillColor, + constFillColor, constFillColor, constFillColor, + constFillColor }; + return checkRectangles(aBitmap, aExpected); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/common.cxx b/vcl/backendtest/outputdevice/common.cxx new file mode 100644 index 000000000..a5d032315 --- /dev/null +++ b/vcl/backendtest/outputdevice/common.cxx @@ -0,0 +1,478 @@ +/* -*- 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 <bitmapwriteaccess.hxx> +#include <salgdi.hxx> + +namespace vcl::test { + +namespace +{ + +int deltaColor(BitmapColor aColor1, BitmapColor aColor2) +{ + int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed()); + int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen()); + int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue()); + + return std::max(std::max(deltaR, deltaG), deltaB); +} + +void checkValue(BitmapScopedWriteAccess& pAccess, int x, int y, Color aExpected, + int& nNumberOfQuirks, int& nNumberOfErrors, bool bQuirkMode, int nColorDeltaThresh = 0) +{ + const bool bColorize = false; + Color aColor = pAccess->GetPixel(y, x); + int nColorDelta = deltaColor(aColor, aExpected); + + if (nColorDelta <= nColorDeltaThresh) + { + if (bColorize) + pAccess->SetPixel(y, x, COL_LIGHTGREEN); + } + else if (bQuirkMode) + { + nNumberOfQuirks++; + if (bColorize) + pAccess->SetPixel(y, x, COL_YELLOW); + } + else + { + nNumberOfErrors++; + if (bColorize) + pAccess->SetPixel(y, x, COL_LIGHTRED); + } +} + +TestResult checkRect(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor) +{ + BitmapScopedWriteAccess 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) +{ + BitmapScopedWriteAccess 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 (long 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 (long 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) +{ + BitmapScopedWriteAccess 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_BLUE); + +OutputDeviceTestCommon::OutputDeviceTestCommon() +{} + +OUString OutputDeviceTestCommon::getRenderBackendName() const +{ + if (mpVirtualDevice && mpVirtualDevice->GetGraphics()) + { + SalGraphics const * pGraphics = mpVirtualDevice->GetGraphics(); + return pGraphics->getRenderBackendName(); + } + return OUString(); +} + +void OutputDeviceTestCommon::initialSetup(long nWidth, long nHeight, Color aColor, bool bEnableAA, bool bAlphaVirtualDevice) +{ + if (bAlphaVirtualDevice) + mpVirtualDevice = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); + else + mpVirtualDevice = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT); + + maVDRectangle = tools::Rectangle(Point(), Size (nWidth, nHeight)); + mpVirtualDevice->SetOutputSizePixel(maVDRectangle.GetSize()); + if (bEnableAA) + mpVirtualDevice->SetAntialiasing(AntialiasingFlags::EnableB2dDraw | AntialiasingFlags::PixelSnapHairline); + else + mpVirtualDevice->SetAntialiasing(AntialiasingFlags::NONE); + mpVirtualDevice->SetBackground(Wallpaper(aColor)); + mpVirtualDevice->Erase(); +} + +TestResult OutputDeviceTestCommon::checkLines(Bitmap& rBitmap) +{ + return checkHorizontalVerticalDiagonalLines(rBitmap, constLineColor, 0); +} + +TestResult OutputDeviceTestCommon::checkAALines(Bitmap& rBitmap) +{ + return checkHorizontalVerticalDiagonalLines(rBitmap, constLineColor, 30); // 30 color values threshold delta +} + +static void checkResult(TestResult eResult, TestResult & eTotal) +{ + if (eTotal == TestResult::Failed) + return; + + if (eResult == TestResult::Failed) + eTotal = TestResult::Failed; + + if (eResult == TestResult::PassedWithQuirks) + eTotal = TestResult::PassedWithQuirks; +} + +TestResult OutputDeviceTestCommon::checkInvertRectangle(Bitmap& aBitmap) +{ + TestResult aReturnValue = TestResult::Passed; + TestResult eResult; + + std::vector<Color> aExpected{ COL_WHITE, COL_WHITE }; + eResult = checkRectangles(aBitmap, aExpected); + checkResult(eResult, aReturnValue); + + eResult = checkFilled(aBitmap, tools::Rectangle(Point(2, 2), Size(8, 8)), COL_LIGHTCYAN); + checkResult(eResult, aReturnValue); + + eResult = checkFilled(aBitmap, tools::Rectangle(Point(10, 2), Size(8, 8)), COL_LIGHTMAGENTA); + checkResult(eResult, aReturnValue); + + eResult = checkFilled(aBitmap, tools::Rectangle(Point(2, 10), Size(8, 8)), COL_YELLOW); + checkResult(eResult, aReturnValue); + + eResult = checkFilled(aBitmap, tools::Rectangle(Point(10, 10), Size(8, 8)), COL_BLACK); + checkResult(eResult, aReturnValue); + + return aReturnValue; +} + +TestResult OutputDeviceTestCommon::checkChecker(Bitmap& rBitmap, sal_Int32 nStartX, sal_Int32 nEndX, sal_Int32 nStartY, sal_Int32 nEndY, std::vector<Color> const & rExpected) +{ + TestResult aReturnValue = TestResult::Passed; + + int choice = 0; + for (sal_Int32 y = nStartY; y <= nEndY; ++y) + { + for (sal_Int32 x = nStartX; x <= nEndX; ++x) + { + TestResult eResult = checkFilled(rBitmap, tools::Rectangle(Point(x, y), Size(1, 1)), rExpected[choice % 2]); + checkResult(eResult, aReturnValue); + choice++; + } + choice++; + } + return aReturnValue; +} + +TestResult OutputDeviceTestCommon::checkInvertN50Rectangle(Bitmap& aBitmap) +{ + TestResult aReturnValue = TestResult::Passed; + TestResult eResult; + + std::vector<Color> aExpected{ COL_WHITE, COL_WHITE }; + eResult = checkRectangles(aBitmap, aExpected); + checkResult(eResult, aReturnValue); + + eResult = checkChecker(aBitmap, 2, 9, 2, 9, { COL_LIGHTCYAN, COL_LIGHTRED }); + checkResult(eResult, aReturnValue); + eResult = checkChecker(aBitmap, 2, 9, 10, 17, { COL_YELLOW, COL_LIGHTBLUE }); + checkResult(eResult, aReturnValue); + eResult = checkChecker(aBitmap, 10, 17, 2, 9, { COL_LIGHTMAGENTA, COL_LIGHTGREEN }); + checkResult(eResult, aReturnValue); + eResult = checkChecker(aBitmap, 10, 17, 10, 17, { COL_BLACK, COL_WHITE }); + checkResult(eResult, aReturnValue); + + return aReturnValue; +} + +TestResult OutputDeviceTestCommon::checkInvertTrackFrameRectangle(Bitmap& aBitmap) +{ + std::vector<Color> aExpected + { + COL_WHITE, COL_WHITE + }; + return checkRectangles(aBitmap, aExpected); +} + +TestResult OutputDeviceTestCommon::checkRectangle(Bitmap& aBitmap) +{ + std::vector<Color> aExpected + { + constBackgroundColor, constBackgroundColor, constLineColor, + constBackgroundColor, constBackgroundColor, constLineColor, constBackgroundColor + }; + return checkRectangles(aBitmap, aExpected); +} + +TestResult OutputDeviceTestCommon::checkRectangleAA(Bitmap& aBitmap) +{ + std::vector<Color> aExpected + { + constBackgroundColor, constBackgroundColor, constLineColor, + constBackgroundColor, constBackgroundColor, constLineColor, constBackgroundColor + }; + return checkRectangles(aBitmap, aExpected); +} + +TestResult OutputDeviceTestCommon::checkFilledRectangle(Bitmap& aBitmap, bool useLineColor) +{ + std::vector<Color> aExpected + { + constBackgroundColor, constBackgroundColor, + useLineColor ? constLineColor : constFillColor, + constFillColor, constFillColor, constFillColor, constFillColor + }; + return checkRectangles(aBitmap, aExpected); +} + +TestResult OutputDeviceTestCommon::checkFilled(Bitmap& rBitmap, tools::Rectangle aRectangle, Color aExpectedColor) +{ + BitmapScopedWriteAccess pAccess(rBitmap); + + TestResult aResult = TestResult::Passed; + int nNumberOfQuirks = 0; + int nNumberOfErrors = 0; + + for (long y = aRectangle.Top(); y < aRectangle.Top() + aRectangle.GetHeight(); y++) + { + for (long x = aRectangle.Left(); x < aRectangle.Left() + aRectangle.GetWidth(); x++) + { + checkValue(pAccess, x, y, aExpectedColor, nNumberOfQuirks, nNumberOfErrors, false); + } + } + + if (nNumberOfQuirks > 0) + aResult = TestResult::PassedWithQuirks; + + if (nNumberOfErrors > 0) + aResult = TestResult::Failed; + + return aResult; +} + +TestResult OutputDeviceTestCommon::checkRectangles(Bitmap& aBitmap, std::vector<Color>& aExpectedColors) +{ + TestResult aReturnValue = TestResult::Passed; + for (size_t i = 0; i < aExpectedColors.size(); i++) + { + TestResult eResult = checkRect(aBitmap, i, aExpectedColors[i]); + + if (eResult == TestResult::Failed) + aReturnValue = TestResult::Failed; + if (eResult == TestResult::PassedWithQuirks && aReturnValue != TestResult::Failed) + aReturnValue = TestResult::PassedWithQuirks; + } + return aReturnValue; +} + +TestResult OutputDeviceTestCommon::checkRectangle(Bitmap& rBitmap, int aLayerNumber, Color aExpectedColor) +{ + return checkRect(rBitmap, aLayerNumber, aExpectedColor); +} + +tools::Rectangle OutputDeviceTestCommon::alignToCenter(tools::Rectangle aRect1, tools::Rectangle aRect2) +{ + Point aPoint((aRect1.GetWidth() / 2.0) - (aRect2.GetWidth() / 2.0), + (aRect1.GetHeight() / 2.0) - (aRect2.GetHeight() / 2.0)); + + return tools::Rectangle(aPoint, aRect2.GetSize()); +} + +TestResult OutputDeviceTestCommon::checkDiamond(Bitmap& rBitmap) +{ + return checkDiamondLine(rBitmap, 1, constLineColor); +} + +void OutputDeviceTestCommon::createDiamondPoints(tools::Rectangle rRect, int nOffset, + Point& rPoint1, Point& rPoint2, + Point& rPoint3, Point& rPoint4) +{ + 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(tools::Rectangle rRect, + Point& rHorizontalLinePoint1, Point& rHorizontalLinePoint2, + Point& rVerticalLinePoint1, Point& rVerticalLinePoint2, + Point& rDiagonalLinePoint1, Point& rDiagonalLinePoint2) +{ + rHorizontalLinePoint1 = Point(4, 1); + rHorizontalLinePoint2 = Point(rRect.Right() - 1, 1); + + rVerticalLinePoint1 = Point(1, 4); + rVerticalLinePoint2 = Point(1,rRect.Bottom() - 1); + + rDiagonalLinePoint1 = Point(1, 1); + rDiagonalLinePoint2 = Point(rRect.Right() - 1, rRect.Bottom() - 1); +} + +TestResult OutputDeviceTestCommon::checkBezier(Bitmap& rBitmap) +{ + std::vector<Color> aExpected + { + constBackgroundColor, constBackgroundColor + }; + // Check the bezier doesn't go over to the margins first + // TODO extend the check with more exact assert + return checkRectangles(rBitmap, aExpected); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/gradient.cxx b/vcl/backendtest/outputdevice/gradient.cxx new file mode 100644 index 000000000..9880fedd1 --- /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> +#include <vcl/gradient.hxx> + +namespace vcl::test { + +Bitmap OutputDeviceTestGradient::setupLinearGradient() +{ + initialSetup(12, 12, constBackgroundColor); + + Gradient aGradient(GradientStyle::Linear, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00)); + aGradient.SetAngle(900); + tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1, + maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1); + mpVirtualDevice->DrawGradient(aDrawRect, aGradient); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestGradient::setupRadialGradient() +{ + initialSetup(12, 12, constBackgroundColor); + + Gradient aGradient(GradientStyle::Radial, Color(0xFF, 0xFF, 0xFF), Color(0x00, 0x00, 0x00)); + tools::Rectangle aDrawRect(maVDRectangle.Left() + 1, maVDRectangle.Top() + 1, + maVDRectangle.Right() - 1, maVDRectangle.Bottom() - 1); + mpVirtualDevice->DrawGradient(aDrawRect, aGradient); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/line.cxx b/vcl/backendtest/outputdevice/line.cxx new file mode 100644 index 000000000..5b5d73261 --- /dev/null +++ b/vcl/backendtest/outputdevice/line.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <vcl/bitmapaccess.hxx> + +#include <list> + +namespace vcl::test { + +namespace +{ + +void drawLineOffset(OutputDevice& rDevice, tools::Rectangle const & 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(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + drawLineOffset(*mpVirtualDevice, maVDRectangle, 2); + drawLineOffset(*mpVirtualDevice, maVDRectangle, 5); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestLine::setupDiamond() +{ + initialSetup(11, 11, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + Point aPoint1, aPoint2, aPoint3, aPoint4; + OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3, aPoint4); + + mpVirtualDevice->DrawLine(aPoint1, aPoint2); + mpVirtualDevice->DrawLine(aPoint2, aPoint3); + mpVirtualDevice->DrawLine(aPoint3, aPoint4); + mpVirtualDevice->DrawLine(aPoint4, aPoint1); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestLine::setupLines() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + Point aHorizontalLinePoint1, aHorizontalLinePoint2; + Point aVerticalLinePoint1, aVerticalLinePoint2; + Point aDiagonalLinePoint1, aDiagonalLinePoint2; + + OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints( + maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2, + aVerticalLinePoint1, aVerticalLinePoint2, + aDiagonalLinePoint1, aDiagonalLinePoint2); + + mpVirtualDevice->DrawLine(aHorizontalLinePoint1, aHorizontalLinePoint2); + mpVirtualDevice->DrawLine(aVerticalLinePoint1, aVerticalLinePoint2); + mpVirtualDevice->DrawLine(aDiagonalLinePoint1, aDiagonalLinePoint2); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestLine::setupAALines() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetAntialiasing(AntialiasingFlags::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()); +} + +Bitmap OutputDeviceTestLine::setupDashedLine() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + tools::Rectangle rectangle = maVDRectangle; + rectangle.shrink(2); + + std::vector stroke({ 2.0, 1.0 }); + mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), + basegfx::B2DPolygon{ + basegfx::B2DPoint(rectangle.getX(), rectangle.getY()), + basegfx::B2DPoint(rectangle.getX(), rectangle.getY() + rectangle.getHeight()), + basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(), + rectangle.getY() + rectangle.getHeight()), + basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(), rectangle.getY()), + basegfx::B2DPoint(rectangle.getX(), rectangle.getY())}, + 1, 0, &stroke, basegfx::B2DLineJoin::NONE, css::drawing::LineCap_BUTT, basegfx::deg2rad(15.0), true ); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +TestResult OutputDeviceTestLine::checkDashedLine(Bitmap& rBitmap) +{ + TestResult returnValue = TestResult::Passed; + for (int i = 0; i < 7; i++) + { + TestResult eResult = TestResult::Passed; + if( i == 2 ) + { + // Build a sequence of pixels for the drawn rectangle border, + // check that they alternate appropriately (there should be + // normally 2 line, 1 background). + std::list< bool > dash; // true - line color, false - background + const int width = rBitmap.GetSizePixel().Width(); + const int height = rBitmap.GetSizePixel().Height(); + BitmapReadAccess access(rBitmap); + for( int x = 2; x < width - 2; ++x ) + dash.push_back( access.GetPixel( 2, x ) == constLineColor ); + for( int y = 3; y < height - 3; ++y ) + dash.push_back( access.GetPixel( y, width - 3 ) == constLineColor ); + for( int x = width - 3; x >= 2; --x ) + dash.push_back( access.GetPixel( height - 3, x ) == constLineColor ); + for( int y = height - 4; y >= 3; --y ) + dash.push_back( access.GetPixel( y, 2 ) == constLineColor ); + for( int x = 2; x < width - 2; ++x ) // repeat, to check also the corner + dash.push_back( access.GetPixel( 2, x ) == constLineColor ); + bool last = false; + int lastCount = 0; + while( !dash.empty()) + { + if( dash.front() == last ) + { + ++lastCount; + if( lastCount > ( last ? 4 : 3 )) + eResult = TestResult::Failed; + else if( lastCount > ( last ? 3 : 2 ) && eResult != TestResult::Failed) + eResult = TestResult::PassedWithQuirks; + } + else + { + last = dash.front(); + lastCount = 1; + } + dash.pop_front(); + } + } + else + { + eResult = OutputDeviceTestCommon::checkRectangle(rBitmap, i, constBackgroundColor); + } + + if (eResult == TestResult::Failed) + returnValue = TestResult::Failed; + if (eResult == TestResult::PassedWithQuirks && returnValue != TestResult::Failed) + returnValue = TestResult::PassedWithQuirks; + } + return returnValue; +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/outputdevice.cxx b/vcl/backendtest/outputdevice/outputdevice.cxx new file mode 100644 index 000000000..07d66ffb4 --- /dev/null +++ b/vcl/backendtest/outputdevice/outputdevice.cxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +namespace vcl::test { + +Bitmap OutputDeviceTestAnotherOutDev::setupDrawOutDev() +{ + ScopedVclPtrInstance<VirtualDevice> pSourceDev; + Size aSourceSize(9, 9); + pSourceDev->SetOutputSizePixel(aSourceSize); + pSourceDev->SetBackground(Wallpaper(constFillColor)); + pSourceDev->Erase(); + + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->DrawOutDev(Point(2, 2), aSourceSize, Point(), aSourceSize, *pSourceDev); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestAnotherOutDev::setupXOR() +{ + initialSetup(13, 13, constBackgroundColor); + + tools::Rectangle aDrawRectangle(maVDRectangle); + aDrawRectangle.shrink(2); + + tools::Rectangle aScissorRectangle(maVDRectangle); + aScissorRectangle.shrink(4); + + mpVirtualDevice->SetRasterOp(RasterOp::Xor); + mpVirtualDevice->SetFillColor(constFillColor); + mpVirtualDevice->DrawRect(aDrawRectangle); + + mpVirtualDevice->SetRasterOp(RasterOp::N0); + mpVirtualDevice->SetFillColor(COL_BLACK); + mpVirtualDevice->DrawRect(aScissorRectangle); + + mpVirtualDevice->SetRasterOp(RasterOp::Xor); + mpVirtualDevice->SetFillColor(constFillColor); + mpVirtualDevice->DrawRect(aDrawRectangle); + + mpVirtualDevice->SetRasterOp(RasterOp::Xor); + mpVirtualDevice->SetLineColor(constFillColor); + mpVirtualDevice->SetFillColor(); + // Rectangle drawn twice is a no-op. + aDrawRectangle = maVDRectangle; + mpVirtualDevice->DrawRect(aDrawRectangle); + mpVirtualDevice->DrawRect(aDrawRectangle); + // Rectangle drawn three times is like drawing once. + aDrawRectangle.shrink(1); + mpVirtualDevice->DrawRect(aDrawRectangle); + mpVirtualDevice->DrawRect(aDrawRectangle); + mpVirtualDevice->DrawRect(aDrawRectangle); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +TestResult OutputDeviceTestAnotherOutDev::checkDrawOutDev(Bitmap& rBitmap) +{ + std::vector<Color> aExpected + { + constBackgroundColor, constBackgroundColor, + constFillColor, constFillColor, constFillColor, constFillColor, constFillColor + }; + return checkRectangles(rBitmap, aExpected); +} + +TestResult OutputDeviceTestAnotherOutDev::checkXOR(Bitmap& rBitmap) +{ + Color xorColor( constBackgroundColor.GetRed() ^ constFillColor.GetRed(), + constBackgroundColor.GetGreen() ^ constFillColor.GetGreen(), + constBackgroundColor.GetBlue() ^ constFillColor.GetBlue()); + std::vector<Color> aExpected + { + constBackgroundColor, xorColor, + constBackgroundColor, constBackgroundColor, + constFillColor, constFillColor, + constFillColor + }; + return checkRectangles(rBitmap, aExpected); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/pixel.cxx b/vcl/backendtest/outputdevice/pixel.cxx new file mode 100644 index 000000000..71997868f --- /dev/null +++ b/vcl/backendtest/outputdevice/pixel.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +namespace vcl::test { + +namespace +{ + +void drawPixelOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset) +{ + 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(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + drawPixelOffset(*mpVirtualDevice, maVDRectangle, 2); + drawPixelOffset(*mpVirtualDevice, maVDRectangle, 5); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/polygon.cxx b/vcl/backendtest/outputdevice/polygon.cxx new file mode 100644 index 000000000..8d207ade9 --- /dev/null +++ b/vcl/backendtest/outputdevice/polygon.cxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +namespace vcl::test { + +namespace +{ + +void drawPolygonOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset, int nFix = 0) +{ + // Note: According to https://lists.freedesktop.org/archives/libreoffice/2019-November/083709.html + // filling polygons always skips the right-most and bottom-most pixels, in order to avoid + // overlaps when drawing adjacent polygons. Specifying nFix = 1 allows to visually compensate + // for this by making the polygon explicitly larger. + tools::Polygon aPolygon(4); + aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Top() + nOffset), 0); + aPolygon.SetPoint(Point(rRect.Right() - nOffset + nFix, rRect.Top() + nOffset), 1); + aPolygon.SetPoint(Point(rRect.Right() - nOffset + nFix, rRect.Bottom() - nOffset + nFix), 2); + aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Bottom() - nOffset + nFix), 3); + aPolygon.Optimize(PolyOptimizeFlags::CLOSE); + + rDevice.DrawPolygon(aPolygon); +} + +} // end anonymous namespace + +Bitmap OutputDeviceTestPolygon::setupRectangle(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2); + drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 5); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolygon::setupFilledRectangle(bool useLineColor) +{ + initialSetup(13, 13, constBackgroundColor); + + if(useLineColor) + mpVirtualDevice->SetLineColor(constLineColor); + else + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(constFillColor); + drawPolygonOffset(*mpVirtualDevice, maVDRectangle, 2, useLineColor ? 0 : 1); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolygon::setupDiamond() +{ + initialSetup(11, 11, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + Point aPoint1, aPoint2, aPoint3, aPoint4; + OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3, aPoint4); + + tools::Polygon aPolygon(4); + + aPolygon.SetPoint(aPoint1, 0); + aPolygon.SetPoint(aPoint2, 1); + aPolygon.SetPoint(aPoint3, 2); + aPolygon.SetPoint(aPoint4, 3); + aPolygon.Optimize(PolyOptimizeFlags::CLOSE); + + mpVirtualDevice->DrawPolygon(aPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolygon::setupLines() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + Point aHorizontalLinePoint1, aHorizontalLinePoint2; + Point aVerticalLinePoint1, aVerticalLinePoint2; + Point aDiagonalLinePoint1, aDiagonalLinePoint2; + + OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints( + maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2, + aVerticalLinePoint1, aVerticalLinePoint2, + aDiagonalLinePoint1, aDiagonalLinePoint2); + + tools::Polygon aHorizontalPolygon(2); + aHorizontalPolygon.SetPoint(aHorizontalLinePoint1, 0); + aHorizontalPolygon.SetPoint(aHorizontalLinePoint2, 1); + mpVirtualDevice->DrawPolygon(aHorizontalPolygon); + + tools::Polygon aVerticalPolygon(2); + aVerticalPolygon.SetPoint(aVerticalLinePoint1, 0); + aVerticalPolygon.SetPoint(aVerticalLinePoint2, 1); + mpVirtualDevice->DrawPolygon(aVerticalPolygon); + + tools::Polygon aDiagonalPolygon(2); + aDiagonalPolygon.SetPoint(aDiagonalLinePoint1, 0); + aDiagonalPolygon.SetPoint(aDiagonalLinePoint2, 1); + mpVirtualDevice->DrawPolygon(aDiagonalPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolygon::setupAALines() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetAntialiasing(AntialiasingFlags::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 000000000..e1d1fd9e0 --- /dev/null +++ b/vcl/backendtest/outputdevice/polyline.cxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +namespace vcl::test { + +namespace +{ + +void drawPolyLineOffset(OutputDevice& rDevice, tools::Rectangle const & 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(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2); + drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyLine::setupDiamond() +{ + initialSetup(11, 11, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + Point aPoint1, aPoint2, aPoint3, aPoint4; + OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3, aPoint4); + + tools::Polygon aPolygon(4); + + aPolygon.SetPoint(aPoint1, 0); + aPolygon.SetPoint(aPoint2, 1); + aPolygon.SetPoint(aPoint3, 2); + aPolygon.SetPoint(aPoint4, 3); + aPolygon.Optimize(PolyOptimizeFlags::CLOSE); + + mpVirtualDevice->DrawPolyLine(aPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyLine::setupLines() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + Point aHorizontalLinePoint1, aHorizontalLinePoint2; + Point aVerticalLinePoint1, aVerticalLinePoint2; + Point aDiagonalLinePoint1, aDiagonalLinePoint2; + + OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints( + maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2, + aVerticalLinePoint1, aVerticalLinePoint2, + aDiagonalLinePoint1, aDiagonalLinePoint2); + + tools::Polygon aHorizontalPolygon(2); + aHorizontalPolygon.SetPoint(aHorizontalLinePoint1, 0); + aHorizontalPolygon.SetPoint(aHorizontalLinePoint2, 1); + mpVirtualDevice->DrawPolyLine(aHorizontalPolygon); + + tools::Polygon aVerticalPolygon(2); + aVerticalPolygon.SetPoint(aVerticalLinePoint1, 0); + aVerticalPolygon.SetPoint(aVerticalLinePoint2, 1); + mpVirtualDevice->DrawPolyLine(aVerticalPolygon); + + tools::Polygon aDiagonalPolygon(2); + aDiagonalPolygon.SetPoint(aDiagonalLinePoint1, 0); + aDiagonalPolygon.SetPoint(aDiagonalLinePoint2, 1); + mpVirtualDevice->DrawPolyLine(aDiagonalPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyLine::setupAALines() +{ + initialSetup(13, 13, constBackgroundColor); + + mpVirtualDevice->SetAntialiasing(AntialiasingFlags::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/polyline_b2d.cxx b/vcl/backendtest/outputdevice/polyline_b2d.cxx new file mode 100644 index 000000000..65658d7ae --- /dev/null +++ b/vcl/backendtest/outputdevice/polyline_b2d.cxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> +#include <vcl/bitmapex.hxx> + +namespace vcl::test +{ +namespace +{ +void drawPolyLineOffset(OutputDevice& rDevice, tools::Rectangle const& rRect, int nOffset) +{ + basegfx::B2DPolygon aPolygon{ + basegfx::B2DPoint(rRect.Left() + nOffset, rRect.Top() + nOffset), + basegfx::B2DPoint(rRect.Right() - nOffset, rRect.Top() + nOffset), + basegfx::B2DPoint(rRect.Right() - nOffset, rRect.Bottom() - nOffset), + basegfx::B2DPoint(rRect.Left() + nOffset, rRect.Bottom() - nOffset), + }; + aPolygon.setClosed(true); + + rDevice.DrawPolyLine(aPolygon, 0.0); // draw hairline +} + +void addDiamondPoints(tools::Rectangle rRect, int nOffset, basegfx::B2DPolygon& rPolygon) +{ + double midPointX = rRect.Left() + (rRect.Right() - rRect.Left()) / 2.0; + double midPointY = rRect.Top() + (rRect.Bottom() - rRect.Top()) / 2.0; + + rPolygon.append({ midPointX, midPointY - nOffset }); + rPolygon.append({ midPointX + nOffset, midPointY }); + rPolygon.append({ midPointX, midPointY + nOffset }); + rPolygon.append({ midPointX - nOffset, midPointY }); +} + +} // end anonymous namespace + +Bitmap OutputDeviceTestPolyLineB2D::setupRectangle(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 2); + drawPolyLineOffset(*mpVirtualDevice, maVDRectangle, 5); + + return mpVirtualDevice->GetBitmapEx(maVDRectangle.TopLeft(), maVDRectangle.GetSize()) + .GetBitmap(); +} + +Bitmap OutputDeviceTestPolyLineB2D::setupDiamond() +{ + initialSetup(11, 11, constBackgroundColor); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + basegfx::B2DPolygon aPolygon; + addDiamondPoints(maVDRectangle, 4, aPolygon); + aPolygon.setClosed(true); + + mpVirtualDevice->DrawPolyLine(aPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyLineB2D::setupBezier() +{ + initialSetup(21, 21, constBackgroundColor, false); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + basegfx::B2DPolygon aPolygon; + addDiamondPoints(maVDRectangle, 8, aPolygon); + aPolygon.setClosed(true); + + double minX = maVDRectangle.Left() + 4; + double maxX = maVDRectangle.Right() - 4; + double minY = maVDRectangle.Top() + 4; + double maxY = maVDRectangle.Bottom() - 4; + + aPolygon.setControlPoints(0, { minX, minY }, { maxX, minY }); + aPolygon.setControlPoints(1, { maxX, minY }, { maxX, maxY }); + aPolygon.setControlPoints(2, { maxX, maxY }, { minX, maxY }); + aPolygon.setControlPoints(3, { minX, maxY }, { minX, minY }); + + mpVirtualDevice->DrawPolyLine(aPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyLineB2D::setupAABezier() +{ + initialSetup(21, 21, constBackgroundColor, true); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + basegfx::B2DPolygon aPolygon; + addDiamondPoints(maVDRectangle, 8, aPolygon); + aPolygon.setClosed(true); + + double minX = maVDRectangle.Left() + 4; + double maxX = maVDRectangle.Right() - 4; + double minY = maVDRectangle.Top() + 4; + double maxY = maVDRectangle.Bottom() - 4; + + aPolygon.setControlPoints(0, { minX, minY }, { maxX, minY }); + aPolygon.setControlPoints(1, { maxX, minY }, { maxX, maxY }); + aPolygon.setControlPoints(2, { maxX, maxY }, { minX, maxY }); + aPolygon.setControlPoints(3, { minX, maxY }, { minX, minY }); + + mpVirtualDevice->DrawPolyLine(aPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/polypolygon.cxx b/vcl/backendtest/outputdevice/polypolygon.cxx new file mode 100644 index 000000000..a53acbaf7 --- /dev/null +++ b/vcl/backendtest/outputdevice/polypolygon.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + + +namespace vcl::test { + +namespace +{ + +tools::Polygon createPolygonOffset(tools::Rectangle const & rRect, int nOffset, int nFix = 0) +{ + // Note: According to https://lists.freedesktop.org/archives/libreoffice/2019-November/083709.html + // filling polygons always skips the right-most and bottom-most pixels, in order to avoid + // overlaps when drawing adjacent polygons. Specifying nFix = 1 allows to visually compensate + // for this by making the polygon explicitly larger. + tools::Polygon aPolygon(4); + aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Top() + nOffset), 0); + aPolygon.SetPoint(Point(rRect.Right() - nOffset + nFix, rRect.Top() + nOffset), 1); + aPolygon.SetPoint(Point(rRect.Right() - nOffset + nFix, rRect.Bottom() - nOffset + nFix), 2); + aPolygon.SetPoint(Point(rRect.Left() + nOffset, rRect.Bottom() - nOffset + nFix), 3); + aPolygon.Optimize(PolyOptimizeFlags::CLOSE); + return aPolygon; +} + +} // end anonymous namespace + +Bitmap OutputDeviceTestPolyPolygon::setupRectangle(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + tools::PolyPolygon aPolyPolygon(2); + aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2)); + aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 5)); + + mpVirtualDevice->DrawPolyPolygon(aPolyPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyPolygon::setupFilledRectangle(bool useLineColor) +{ + initialSetup(13, 13, constBackgroundColor); + + if(useLineColor) + mpVirtualDevice->SetLineColor(constLineColor); + else + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(constFillColor); + + tools::PolyPolygon aPolyPolygon(1); + aPolyPolygon.Insert(createPolygonOffset(maVDRectangle, 2, useLineColor ? 0 : 1)); + + mpVirtualDevice->DrawPolyPolygon(aPolyPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/polypolygon_b2d.cxx b/vcl/backendtest/outputdevice/polypolygon_b2d.cxx new file mode 100644 index 000000000..737cfae19 --- /dev/null +++ b/vcl/backendtest/outputdevice/polypolygon_b2d.cxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <test/outputdevice.hxx> + +namespace vcl::test +{ +namespace +{ +basegfx::B2DPolygon createPolygonOffset(tools::Rectangle const& rRect, int nOffset, int nFix = 0) +{ + // Note: According to https://lists.freedesktop.org/archives/libreoffice/2019-November/083709.html + // filling polygons always skips the right-most and bottom-most pixels, in order to avoid + // overlaps when drawing adjacent polygons. Specifying nFix = 1 allows to visually compensate + // for this by making the polygon explicitly larger. + basegfx::B2DPolygon aPolygon{ + basegfx::B2DPoint(rRect.Left() + nOffset, rRect.Top() + nOffset), + basegfx::B2DPoint(rRect.Right() - nOffset + nFix, rRect.Top() + nOffset), + basegfx::B2DPoint(rRect.Right() - nOffset + nFix, rRect.Bottom() - nOffset + nFix), + basegfx::B2DPoint(rRect.Left() + nOffset, rRect.Bottom() - nOffset + nFix), + }; + aPolygon.setClosed(true); + return aPolygon; +} + +} // end anonymous namespace + +Bitmap OutputDeviceTestPolyPolygonB2D::setupRectangle(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + basegfx::B2DPolyPolygon aPolyPolygon; + aPolyPolygon.append(createPolygonOffset(maVDRectangle, 2)); + aPolyPolygon.append(createPolygonOffset(maVDRectangle, 5)); + + mpVirtualDevice->DrawPolyPolygon(aPolyPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestPolyPolygonB2D::setupFilledRectangle(bool useLineColor) +{ + initialSetup(13, 13, constBackgroundColor); + + if (useLineColor) + mpVirtualDevice->SetLineColor(constLineColor); + else + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(constFillColor); + + basegfx::B2DPolyPolygon aPolyPolygon( + createPolygonOffset(maVDRectangle, 2, useLineColor ? 0 : 1)); + + mpVirtualDevice->DrawPolyPolygon(aPolyPolygon); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/backendtest/outputdevice/rectangle.cxx b/vcl/backendtest/outputdevice/rectangle.cxx new file mode 100644 index 000000000..8e7c0ba86 --- /dev/null +++ b/vcl/backendtest/outputdevice/rectangle.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::test { + +namespace +{ + void drawRectOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset) + { + rDevice.DrawRect(tools::Rectangle(rRect.Left() + nOffset, rRect.Top() + nOffset, + rRect.Right() - nOffset, rRect.Bottom() - nOffset)); + + } + + void drawInvertOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset, InvertFlags eFlags) + { + tools::Rectangle aRectangle(rRect.Left() + nOffset, rRect.Top() + nOffset, + rRect.Right() - nOffset, rRect.Bottom() - nOffset); + rDevice.Invert(aRectangle, eFlags); + } + +} // end anonymous namespace + +Bitmap OutputDeviceTestRect::setupFilledRectangle(bool useLineColor) +{ + initialSetup(13, 13, constBackgroundColor); + + if(useLineColor) + mpVirtualDevice->SetLineColor(constLineColor); + else + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(constFillColor); + + drawRectOffset(*mpVirtualDevice, maVDRectangle, 2); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestRect::setupRectangle(bool bEnableAA) +{ + initialSetup(13, 13, constBackgroundColor, bEnableAA); + + mpVirtualDevice->SetLineColor(constLineColor); + mpVirtualDevice->SetFillColor(); + + drawRectOffset(*mpVirtualDevice, maVDRectangle, 2); + drawRectOffset(*mpVirtualDevice, maVDRectangle, 5); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestRect::setupInvert_NONE() +{ + initialSetup(20, 20, COL_WHITE); + + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(COL_LIGHTRED); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 2), Size(8, 8))); + mpVirtualDevice->SetFillColor(COL_LIGHTGREEN); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(10, 2), Size(8, 8))); + mpVirtualDevice->SetFillColor(COL_LIGHTBLUE); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 10), Size(8, 8))); + + drawInvertOffset(*mpVirtualDevice, maVDRectangle, 2, InvertFlags::NONE); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestRect::setupInvert_N50() +{ + initialSetup(20, 20, COL_WHITE); + + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(COL_LIGHTRED); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 2), Size(8, 8))); + mpVirtualDevice->SetFillColor(COL_LIGHTGREEN); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(10, 2), Size(8, 8))); + mpVirtualDevice->SetFillColor(COL_LIGHTBLUE); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 10), Size(8, 8))); + + drawInvertOffset(*mpVirtualDevice, maVDRectangle, 2, InvertFlags::N50); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +Bitmap OutputDeviceTestRect::setupInvert_TrackFrame() +{ + initialSetup(20, 20, COL_WHITE); + + mpVirtualDevice->SetLineColor(); + mpVirtualDevice->SetFillColor(COL_LIGHTRED); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 2), Size(8, 8))); + mpVirtualDevice->SetFillColor(COL_LIGHTGREEN); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(10, 2), Size(8, 8))); + mpVirtualDevice->SetFillColor(COL_LIGHTBLUE); + mpVirtualDevice->DrawRect(tools::Rectangle(Point(2, 10), Size(8, 8))); + + drawInvertOffset(*mpVirtualDevice, maVDRectangle, 2, InvertFlags::TrackFrame); + + return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize()); +} + +} // end namespace vcl::test + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |