Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/vcl/qa/cppunit/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 87 kB image not shown  

Quelle  outdev.cxx   Sprache: C

 
/* -*- 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 <tools/color.hxx>
#include <test/bootstrapfixture.hxx>
#include <test/outputdevice.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/vector/b2enums.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>

#include <vcl/gradient.hxx>
#include <vcl/lineinfo.hxx>
#include <vcl/print.hxx>
#include <vcl/rendercontext/RasterOp.hxx>
#include <vcl/virdev.hxx>
#include <vcl/window.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/metaact.hxx>

#include <vcl/BitmapWriteAccess.hxx>
#include <bufferdevice.hxx>
#include <window.h>

const size_t INITIAL_SETUP_ACTION_COUNT = 5;

class VclOutdevTest : public test::BootstrapFixture
{
public:
    VclOutdevTest()
        : BootstrapFixture(truefalse)
    {
    }
};

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testGetReadableFontColorPrinter)
{
    ScopedVclPtrInstance<Printer> pPrinter;
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPrinter->GetReadableFontColor(COL_WHITE, COL_WHITE));
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testGetReadableFontColorWindow)
{
    ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
    CPPUNIT_ASSERT_EQUAL(COL_WHITE,
                         pWindow->GetOutDev()->GetReadableFontColor(COL_WHITE, COL_BLACK));
    CPPUNIT_ASSERT_EQUAL(COL_BLACK,
                         pWindow->GetOutDev()->GetReadableFontColor(COL_WHITE, COL_WHITE));
    CPPUNIT_ASSERT_EQUAL(COL_WHITE,
                         pWindow->GetOutDev()->GetReadableFontColor(COL_BLACK, COL_BLACK));
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testPrinterBackgroundColor)
{
    ScopedVclPtrInstance<Printer> pPrinter;
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pPrinter->GetBackgroundColor());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testWindowBackgroundColor)
{
    ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
    pWindow->SetBackground(Wallpaper(COL_WHITE));
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pWindow->GetBackgroundColor());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testVirtualDevice)
{
// TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
#ifndef MACOSX
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    pVDev->SetOutputSizePixel(Size(32, 32));
    pVDev->SetBackground(Wallpaper(COL_WHITE));

    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetBackgroundColor());

    pVDev->Erase();
    pVDev->DrawPixel(Point(1, 2), COL_BLUE);
    pVDev->DrawPixel(Point(31, 30), COL_RED);

    Size aSize = pVDev->GetOutputSizePixel();
    CPPUNIT_ASSERT_EQUAL(Size(32, 32), aSize);

    Bitmap aBmp = pVDev->GetBitmap(Point(), aSize);

#if 0
    OUString rFileName("/tmp/foo-unx.png");
    try {
        vcl::PNGWriter aWriter( aBmp );
        SvFileStream sOutput( rFileName, StreamMode::WRITE );
        aWriter.Write( sOutput );
        sOutput.Close();
    } catch (...) {
        SAL_WARN("vcl""Error writing png to " << rFileName);
    }
#endif

    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(0, 0)));
#if !defined _WIN32 //TODO: various failures on Windows tinderboxes
    CPPUNIT_ASSERT_EQUAL(COL_BLUE, pVDev->GetPixel(Point(1, 2)));
    CPPUNIT_ASSERT_EQUAL(COL_RED, pVDev->GetPixel(Point(31, 30)));
#endif
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetPixel(Point(30, 31)));

    // Gotcha: y and x swap for BitmapReadAccess: deep joy.
    BitmapScopedReadAccess pAcc(aBmp);
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, static_cast<Color>(pAcc->GetPixel(0, 0)));
#if !defined _WIN32 //TODO: various failures on Windows tinderboxes
    CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<Color>(pAcc->GetPixel(2, 1)));
    CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<Color>(pAcc->GetPixel(30, 31)));
#endif
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, static_cast<Color>(pAcc->GetPixel(31, 30)));

#if 0
    VclPtr<vcl::Window> pWin = VclPtr<WorkWindow>::Create( (vcl::Window *)nullptr );
    CPPUNIT_ASSERT( pWin );
    OutputDevice *pOutDev = pWin.get();
#endif
#endif
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testUseAfterDispose)
{
    // Create a virtual device, enable map mode then dispose it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    pVDev->EnableMapMode();

    pVDev->disposeOnce();

    // Make sure that these don't crash after dispose.
    pVDev->GetInverseViewTransformation();

    pVDev->GetViewTransformation();
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawInvertedBitmap)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetRasterOp(RasterOp::Invert);
    pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
                      MetaActionType::BMP);

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::RASTEROP, pAction->GetType());
    auto pRasterOpAction = static_cast<MetaRasterOpAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(RasterOp::Invert, pRasterOpAction->GetRasterOp());

    pAction = aMtf.GetAction(1);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::RECT, pAction->GetType());
    auto pRectAction = static_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(10, 10)), pRectAction->GetRect());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawBlackBitmap)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
    aBitmap.Erase(COL_RED);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetDrawMode(DrawModeFlags::BlackBitmap);
    pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
                      MetaActionType::BMP);

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::PUSH, pAction->GetType());
    auto pPushAction = static_cast<MetaPushAction*>(pAction);
    bool bLineFillFlag
        = ((vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR) == pPushAction->GetFlags());
    CPPUNIT_ASSERT_MESSAGE("Push flags not LINECOLOR | FILLCOLOR", bLineFillFlag);

    pAction = aMtf.GetAction(1);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
    auto pLineColorAction = static_cast<MetaLineColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pLineColorAction->GetColor());

    pAction = aMtf.GetAction(2);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
    auto pFillColorAction = static_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pFillColorAction->GetColor());

    pAction = aMtf.GetAction(3);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::RECT, pAction->GetType());
    auto pRectAction = static_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(10, 10)), pRectAction->GetRect());

    pAction = aMtf.GetAction(4);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::POP, pAction->GetType());

    // test to see if the color is black
    Bitmap aBlackBmp(pVDev->GetBitmap(Point(0, 0), Size(10, 10)));
    BitmapScopedReadAccess pReadAccess(aBlackBmp);
    const BitmapColor aColor = pReadAccess->GetColor(0, 0);
    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), aColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawWhiteBitmap)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetDrawMode(DrawModeFlags::WhiteBitmap);
    pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
                      MetaActionType::BMP);

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::PUSH, pAction->GetType());
    auto pPushAction = static_cast<MetaPushAction*>(pAction);
    bool bLineFillFlag
        = ((vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR) == pPushAction->GetFlags());
    CPPUNIT_ASSERT_MESSAGE("Push flags not LINECOLOR | FILLCOLOR", bLineFillFlag);

    pAction = aMtf.GetAction(1);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
    auto pLineColorAction = static_cast<MetaLineColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pLineColorAction->GetColor());

    pAction = aMtf.GetAction(2);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
    auto pFillColorAction = static_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pFillColorAction->GetColor());

    pAction = aMtf.GetAction(3);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::RECT, pAction->GetType());
    auto pRectAction = static_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 0), Size(10, 10)), pRectAction->GetRect());

    pAction = aMtf.GetAction(4);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::POP, pAction->GetType());

    // test to see if the color is white
    Bitmap aWhiteBmp(pVDev->GetBitmap(Point(0, 0), Size(10, 10)));
    BitmapScopedReadAccess pReadAccess(aWhiteBmp);
    const BitmapColor aColor = pReadAccess->GetColor(0, 0);
    CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), aColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawBitmap)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
                      MetaActionType::BMP);

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMP, pAction->GetType());
    auto pBmpAction = static_cast<MetaBmpAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(Size(16, 16), pBmpAction->GetBitmap().GetSizePixel());
    CPPUNIT_ASSERT_EQUAL(Point(0, 0), pBmpAction->GetPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawScaleBitmap)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->DrawBitmap(Point(5, 5), Size(10, 10), Point(0, 0), Size(10, 10), aBitmap,
                      MetaActionType::BMPSCALE);

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPSCALE, pAction->GetType());
    auto pBmpScaleAction = static_cast<MetaBmpScaleAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(Size(16, 16), pBmpScaleAction->GetBitmap().GetSizePixel());
    CPPUNIT_ASSERT_EQUAL(Point(5, 5), pBmpScaleAction->GetPoint());
    CPPUNIT_ASSERT_EQUAL(Size(10, 10), pBmpScaleAction->GetSize());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawScalePartBitmap)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->DrawBitmap(Point(0, 0), Size(10, 10), Point(5, 5), Size(10, 10), aBitmap,
                      MetaActionType::BMPSCALEPART);

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPSCALEPART, pAction->GetType());
    auto pBmpScalePartAction = static_cast<MetaBmpScalePartAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(Size(16, 16), pBmpScalePartAction->GetBitmap().GetSizePixel());
    CPPUNIT_ASSERT_EQUAL(Point(5, 5), pBmpScalePartAction->GetSrcPoint());
    CPPUNIT_ASSERT_EQUAL(Size(10, 10), pBmpScalePartAction->GetSrcSize());
    CPPUNIT_ASSERT_EQUAL(Point(0, 0), pBmpScalePartAction->GetDestPoint());
    CPPUNIT_ASSERT_EQUAL(Size(10, 10), pBmpScalePartAction->GetDestSize());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawGrayBitmap)
{
    // draw a red 1x1 bitmap
    Bitmap aBmp(Size(1, 1), vcl::PixelFormat::N24_BPP);
    aBmp.Erase(COL_RED);

    // check to ensure that the bitmap is red
    {
        BitmapScopedReadAccess pReadAccess(aBmp);
        const BitmapColor aColor = pReadAccess->GetColor(0, 0);
        CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), aColor);
    }

    ScopedVclPtrInstance<VirtualDevice> pVDev;

    pVDev->SetDrawMode(DrawModeFlags::GrayBitmap);
    pVDev->DrawBitmap(Point(0, 0), Size(1, 1), Point(0, 0), Size(1, 1), aBmp, MetaActionType::BMP);

    // should be a grey
    Bitmap aVDevBmp(pVDev->GetBitmap(Point(), Size(1, 1)));
    {
        BitmapScopedReadAccess pReadAccess(aVDevBmp);
        const BitmapColor aColor = pReadAccess->GetColor(0, 0);
        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x26, 0x26, 0x26), aColor);
    }
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapExScale)
{
    // Given a 100x100 bitmap:
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(100, 100), vcl::PixelFormat::N24_BPP);
    basegfx::B2DVector aScale(20, 80);
    basegfx::B2DVector aTranslate(80, 0);
    double fRotate = M_PI / 2;
    double fShearX = 0;
    basegfx::B2DHomMatrix aMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
        aScale, fShearX, fRotate, aTranslate);
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    // When drawing that with a transform:
    BitmapEx aBitmapEx(aBitmap);
    pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);

    // Then make sure the bitmap recorded in the metafile doesn't get a scaled down width:
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
    auto pBitmapAction = static_cast<MetaBmpExScaleAction*>(pAction);
    const BitmapEx& rBitmapEx = pBitmapAction->GetBitmapEx();
    Size aTransformedSize = rBitmapEx.GetSizePixel();
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected greater or equal than: 100
    // - Actual  : 80
    // i.e. an unwanted scaling down lead to blurry presentation output.
    CPPUNIT_ASSERT_GREATEREQUAL(static_cast<tools::Long>(100), aTransformedSize.getWidth());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapEx)
{
    // Create a virtual device, and connect a metafile to it.
    // Also create a 16x16 bitmap.
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
    {
        // Fill the top left quarter with black.
        BitmapScopedWriteAccess pWriteAccess(aBitmap);
        pWriteAccess->Erase(COL_WHITE);
        for (int i = 0; i < 8; ++i)
        {
            for (int j = 0; j < 8; ++j)
            {
                pWriteAccess->SetPixel(j, i, COL_BLACK);
            }
        }
    }
    BitmapEx aBitmapEx(aBitmap);
    basegfx::B2DHomMatrix aMatrix;
    aMatrix.scale(8, 8);
    // Rotate 90 degrees clockwise, so the black part goes to the top right.
    aMatrix.rotate(M_PI / 2);
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    // Draw the rotated bitmap on the vdev.
    pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
    auto pBitmapAction = static_cast<MetaBmpExScaleAction*>(pAction);
    const BitmapEx& rBitmapEx = pBitmapAction->GetBitmapEx();
    Size aTransformedSize = rBitmapEx.GetSizePixel();
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 16x16
    // - Actual  : 8x8
    // I.e. the bitmap before scaling was already scaled down, just because it was rotated.
    CPPUNIT_ASSERT_EQUAL(Size(16, 16), aTransformedSize);

    aBitmap = rBitmapEx.GetBitmap();
    BitmapScopedReadAccess pAccess(aBitmap);
    for (int i = 0; i < 16; ++i)
    {
        for (int j = 0; j < 16; ++j)
        {
            BitmapColor aColor = pAccess->GetPixel(j, i);
            Color aExpected = i >= 8 && j < 8 ? COL_BLACK : COL_WHITE;
            std::stringstream ss;
            ss << "Color is expected to be ";
            ss << ((aExpected == COL_WHITE) ? "white" : "black");
            ss << ", is " << aColor.AsRGBHexString();
            ss << " (row " << j << ", col " << i << ")";
            // Without the accompanying fix in place, this test would have failed with:
            // - Expected: c[00000000]
            // - Actual  : c[ffffff00]
            // - Color is expected to be black, is ffffff (row 0, col 8)
            // i.e. the top right quarter of the image was not fully black, there was a white first
            // row.
            CPPUNIT_ASSERT_EQUAL_MESSAGE(ss.str(), aExpected, Color(aColor));
        }
    }
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapExFlip)
{
    // Create a virtual device, and connect a metafile to it.
    // Also create a 16x16 bitmap.
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
    {
        // Fill the top left quarter with black.
        BitmapScopedWriteAccess pWriteAccess(aBitmap);
        pWriteAccess->Erase(COL_WHITE);
        for (int i = 0; i < 8; ++i)
        {
            for (int j = 0; j < 8; ++j)
            {
                pWriteAccess->SetPixel(j, i, COL_BLACK);
            }
        }
    }
    BitmapEx aBitmapEx(aBitmap);
    basegfx::B2DHomMatrix aMatrix;
    // Negative y scale: bitmap should be upside down, so the black part goes to the bottom left.
    aMatrix.scale(8, -8);
    // Rotate 90 degrees clockwise, so the black part goes back to the top left.
    aMatrix.rotate(M_PI / 2);
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    // Draw the scaled and rotated bitmap on the vdev.
    pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
    auto pBitmapAction = static_cast<MetaBmpExScaleAction*>(pAction);
    const BitmapEx& rBitmapEx = pBitmapAction->GetBitmapEx();

    aBitmap = rBitmapEx.GetBitmap();
    BitmapScopedReadAccess pAccess(aBitmap);
    int nX = 8 * 0.25;
    int nY = 8 * 0.25;
    BitmapColor aColor = pAccess->GetPixel(nY, nX);
    std::stringstream ss;
    ss << "Color is expected to be black, is " << aColor.AsRGBHexString();
    ss << " (row " << nY << ", col " << nX << ")";
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: c[00000000]
    // - Actual  : c[ffffff00]
    // - Color is expected to be black, is ffffff (row 2, col 2)
    // i.e. the top left quarter of the image was not black, due to a missing flip.
    CPPUNIT_ASSERT_EQUAL_MESSAGE(ss.str(), COL_BLACK, Color(aColor));
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testRTL)
{
    ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
    pWindow->EnableRTL();
    vcl::RenderContext& rRenderContext = *pWindow->GetOutDev();
    vcl::BufferDevice pBuffer(pWindow, rRenderContext);

    // Without the accompanying fix in place, this test would have failed, because the RTL status
    // from pWindow was not propagated to pBuffer.
    CPPUNIT_ASSERT(pBuffer->IsRTLEnabled());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testRTLGuard)
{
    ScopedVclPtrInstance<vcl::Window> pWindow(nullptr, WB_APP | WB_STDWORK);
    pWindow->EnableRTL();
    pWindow->RequestDoubleBuffering(true);
    ImplFrameData* pFrameData = pWindow->ImplGetWindowImpl()->mpFrameData;
    vcl::PaintBufferGuard aGuard(pFrameData, pWindow);
    // Without the accompanying fix in place, this test would have failed, because the RTL status
    // from pWindow was not propagated to aGuard.
    CPPUNIT_ASSERT(aGuard.GetRenderContext()->IsRTLEnabled());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDefaultFillColor)
{
    // Create a virtual device, and connect a metafile to it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT(pVDev->IsFillColor());
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetFillColor());

    pVDev->SetFillColor();
    CPPUNIT_ASSERT(!pVDev->IsFillColor());
    CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetFillColor());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
    auto pFillAction = static_cast<MetaFillColorAction*>(pAction);
    const Color& rColor = pFillAction->GetColor();
    CPPUNIT_ASSERT_EQUAL(Color(), rColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testTransparentFillColor)
{
    // Create a virtual device, and connect a metafile to it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT(pVDev->IsFillColor());
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetFillColor());

    pVDev->SetFillColor(COL_TRANSPARENT);
    CPPUNIT_ASSERT(pVDev->IsFillColor());
    CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetFillColor());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
    auto pFillAction = static_cast<MetaFillColorAction*>(pAction);
    const Color& rColor = pFillAction->GetColor();
    CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, rColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testFillColor)
{
    // Create a virtual device, and connect a metafile to it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT(pVDev->IsFillColor());
    CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetFillColor());

    pVDev->SetFillColor(COL_RED);
    CPPUNIT_ASSERT(pVDev->IsFillColor());
    CPPUNIT_ASSERT_EQUAL(COL_RED, pVDev->GetFillColor());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
    auto pFillAction = static_cast<MetaFillColorAction*>(pAction);
    const Color& rColor = pFillAction->GetColor();
    CPPUNIT_ASSERT_EQUAL(COL_RED, rColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDefaultLineColor)
{
    // Create a virtual device, and connect a metafile to it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT(pVDev->IsLineColor());
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetLineColor());

    pVDev->SetLineColor();
    CPPUNIT_ASSERT(!pVDev->IsLineColor());
    CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetLineColor());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
    auto pLineAction = static_cast<MetaLineColorAction*>(pAction);
    const Color& rColor = pLineAction->GetColor();
    CPPUNIT_ASSERT_EQUAL(Color(), rColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testTransparentLineColor)
{
    // Create a virtual device, and connect a metafile to it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT(pVDev->IsLineColor());
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetLineColor());

    pVDev->SetLineColor(COL_TRANSPARENT);
    CPPUNIT_ASSERT(!pVDev->IsLineColor());
    CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetLineColor());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
    auto pLineAction = static_cast<MetaLineColorAction*>(pAction);
    const Color& rColor = pLineAction->GetColor();
    CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, rColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testLineColor)
{
    // Create a virtual device, and connect a metafile to it.
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT(pVDev->IsLineColor());
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetLineColor());

    pVDev->SetLineColor(COL_RED);
    CPPUNIT_ASSERT(pVDev->IsLineColor());
    CPPUNIT_ASSERT_EQUAL(COL_RED, pVDev->GetLineColor());
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::LINECOLOR, pAction->GetType());
    auto pLineAction = static_cast<MetaLineColorAction*>(pAction);
    const Color& rColor = pLineAction->GetColor();
    CPPUNIT_ASSERT_EQUAL(COL_RED, rColor);
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testFont)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    // Use Dejavu fonts, they are shipped with LO, so they should be ~always available.
    // Use Sans variant for simpler glyph shapes (no serifs).
    vcl::Font font(u"DejaVu Sans"_ustr, u"Book"_ustr, Size(0, 36));
    font.SetColor(COL_BLACK);
    font.SetFillColor(COL_RED);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetFont(font);
    bool bSameFont(font == pVDev->GetFont());
    CPPUNIT_ASSERT_MESSAGE("Font is not the same", bSameFont);

    // four actions:
    // 1. Font action
    // 2. Text alignment action
    // 3. Text fill color action
    // 4. As not COL_TRANSPARENT (means use system font color), font color action
    size_t nActionsExpected = 4;
    CPPUNIT_ASSERT_EQUAL(nActionsExpected, aMtf.GetActionSize());

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::FONT, pAction->GetType());
    auto pFontAction = static_cast<MetaFontAction*>(pAction);
    bool bSameMetaFont = (font == pFontAction->GetFont());
    CPPUNIT_ASSERT_MESSAGE("Metafile font is not the same", bSameMetaFont);

    pAction = aMtf.GetAction(1);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTALIGN, pAction->GetType());
    auto pTextAlignAction = static_cast<MetaTextAlignAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(font.GetAlignment(), pTextAlignAction->GetTextAlign());

    pAction = aMtf.GetAction(2);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTFILLCOLOR, pAction->GetType());
    auto pTextFillColorAction = static_cast<MetaTextFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(COL_RED, pTextFillColorAction->GetColor());

    pAction = aMtf.GetAction(3);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTCOLOR, pAction->GetType());
    auto pTextColorAction = static_cast<MetaTextColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(COL_BLACK, pTextColorAction->GetColor());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testTransparentFont)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    // Use Dejavu fonts, they are shipped with LO, so they should be ~always available.
    // Use Sans variant for simpler glyph shapes (no serifs).
    vcl::Font font(u"DejaVu Sans"_ustr, u"Book"_ustr, Size(0, 36));
    font.SetColor(COL_TRANSPARENT);

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetFont(font);

    // three actions as it sets the colour to the default system color (and doesn't add a text color action):
    // 1. Font action
    // 2. Text alignment action
    // 3. Text fill color action
    size_t nActionsExpected = 3;
    CPPUNIT_ASSERT_EQUAL(nActionsExpected, aMtf.GetActionSize());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDefaultRefPoint)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetRefPoint();

    CPPUNIT_ASSERT(!pVDev->IsRefPoint());
    CPPUNIT_ASSERT_EQUAL(Point(), pVDev->GetRefPoint());

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::REFPOINT, pAction->GetType());
    auto pRefPointAction = static_cast<MetaRefPointAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(Point(), pRefPointAction->GetRefPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testRefPoint)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetRefPoint(Point(10, 20));

    CPPUNIT_ASSERT(pVDev->IsRefPoint());
    CPPUNIT_ASSERT_EQUAL(Point(10, 20), pVDev->GetRefPoint());

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::REFPOINT, pAction->GetType());
    auto pRefPointAction = static_cast<MetaRefPointAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(Point(10, 20), pRefPointAction->GetRefPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testRasterOp)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetRasterOp(RasterOp::Invert);

    CPPUNIT_ASSERT_EQUAL(RasterOp::Invert, pVDev->GetRasterOp());
    CPPUNIT_ASSERT(pVDev->IsLineColor());
    CPPUNIT_ASSERT(pVDev->IsFillColor());

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::RASTEROP, pAction->GetType());
    auto pRasterOpAction = static_cast<MetaRasterOpAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(RasterOp::Invert, pRasterOpAction->GetRasterOp());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testOutputFlag)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    CPPUNIT_ASSERT(pVDev->IsOutputEnabled());
    CPPUNIT_ASSERT(pVDev->IsDeviceOutputNecessary());

    pVDev->EnableOutput(false);

    CPPUNIT_ASSERT(!pVDev->IsOutputEnabled());
    CPPUNIT_ASSERT(!pVDev->IsDeviceOutputNecessary());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testAntialias)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    CPPUNIT_ASSERT_EQUAL(AntialiasingFlags::NONE, pVDev->GetAntialiasing());

    pVDev->SetAntialiasing(AntialiasingFlags::Enable);

    CPPUNIT_ASSERT_EQUAL(AntialiasingFlags::Enable, pVDev->GetAntialiasing());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawMode)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    CPPUNIT_ASSERT_EQUAL(DrawModeFlags::Default, pVDev->GetDrawMode());

    pVDev->SetDrawMode(DrawModeFlags::BlackLine);

    CPPUNIT_ASSERT_EQUAL(DrawModeFlags::BlackLine, pVDev->GetDrawMode());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testLayoutMode)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT_EQUAL(vcl::text::ComplexTextLayoutFlags::Default, pVDev->GetLayoutMode());

    pVDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiRtl);

    CPPUNIT_ASSERT_EQUAL(vcl::text::ComplexTextLayoutFlags::BiDiRtl, pVDev->GetLayoutMode());

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::LAYOUTMODE, pAction->GetType());
    auto pLayoutModeAction = static_cast<MetaLayoutModeAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(vcl::text::ComplexTextLayoutFlags::BiDiRtl,
                         pLayoutModeAction->GetLayoutMode());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDigitLanguage)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;

    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    CPPUNIT_ASSERT_EQUAL(LANGUAGE_SYSTEM, pVDev->GetDigitLanguage());

    pVDev->SetDigitLanguage(LANGUAGE_GERMAN);

    CPPUNIT_ASSERT_EQUAL(LANGUAGE_GERMAN, pVDev->GetDigitLanguage());

    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL(MetaActionType::TEXTLANGUAGE, pAction->GetType());
    auto pTextLanguageAction = static_cast<MetaTextLanguageAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL(LANGUAGE_GERMAN, pTextLanguageAction->GetTextLanguage());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testStackFunctions)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->Push();
    MetaAction* pAction = aMtf.GetAction(0);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Push action", MetaActionType::PUSH, pAction->GetType());

    pVDev->SetLineColor(COL_RED);
    pVDev->SetFillColor(COL_GREEN);
    pVDev->SetTextColor(COL_BROWN);
    pVDev->SetTextFillColor(COL_BLUE);
    pVDev->SetTextLineColor(COL_MAGENTA);
    pVDev->SetOverlineColor(COL_YELLOW);
    pVDev->SetTextAlign(TextAlign::ALIGN_TOP);
    pVDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiRtl);
    pVDev->SetDigitLanguage(LANGUAGE_FRENCH);
    pVDev->SetRasterOp(RasterOp::N0);
    pVDev->SetMapMode(MapMode(MapUnit::MapTwip));
    pVDev->SetRefPoint(Point(10, 10));

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Text color", COL_BROWN, pVDev->GetTextColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Text fill color", COL_BLUE, pVDev->GetTextFillColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Text line color", COL_MAGENTA, pVDev->GetTextLineColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Text overline color", COL_YELLOW, pVDev->GetOverlineColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Layout mode", vcl::text::ComplexTextLayoutFlags::BiDiRtl,
                                 pVDev->GetLayoutMode());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Language", LANGUAGE_FRENCH, pVDev->GetDigitLanguage());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Raster operation", RasterOp::N0, pVDev->GetRasterOp());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Map mode", MapMode(MapUnit::MapTwip), pVDev->GetMapMode());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Ref point", Point(10, 10), pVDev->GetRefPoint());

    pVDev->Pop();
    pAction = aMtf.GetAction(13);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Pop action", MetaActionType::POP, pAction->GetType());

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default line color", COL_BLACK, pVDev->GetLineColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default fill color", COL_WHITE, pVDev->GetFillColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default text color", COL_BLACK, pVDev->GetTextColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default text fill color", Color(ColorTransparency, 0xFFFFFFFF),
                                 pVDev->GetTextFillColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default text line color", Color(ColorTransparency, 0xFFFFFFFF),
                                 pVDev->GetTextLineColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default overline color", Color(ColorTransparency, 0xFFFFFFFF),
                                 pVDev->GetOverlineColor());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default layout mode", vcl::text::ComplexTextLayoutFlags::Default,
                                 pVDev->GetLayoutMode());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default language", LANGUAGE_SYSTEM, pVDev->GetDigitLanguage());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default raster operation", RasterOp::OverPaint,
                                 pVDev->GetRasterOp());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default map mode", MapMode(MapUnit::MapPixel),
                                 pVDev->GetMapMode());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Default ref point", Point(0, 0), pVDev->GetRefPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testSystemTextColor)
{
    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;

        pVDev->SetSystemTextColor(SystemTextColorFlags::NONE, true);
        CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetTextColor());
        pVDev->SetSystemTextColor(SystemTextColorFlags::Mono, false);
        CPPUNIT_ASSERT_EQUAL(COL_BLACK, pVDev->GetTextColor());
    }

    {
        ScopedVclPtrInstance<Printer> pPrinter;
        pPrinter->SetSystemTextColor(SystemTextColorFlags::NONE, true);
        CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPrinter->GetTextColor());
    }
}

namespace
{
class WaveLineTester : public OutputDevice
{
public:
    WaveLineTester()
        : OutputDevice(OUTDEV_VIRDEV)
    {
    }

    bool AcquireGraphics() const override { return true; }
    void ReleaseGraphics(bool) override {}
    bool UsePolyPolygonForComplexGradient() override { return false; }
    bool CanAnimate() const override { return false; }

    bool testShouldDrawWavePixelAsRect(tools::Long nLineWidth)
    {
        return shouldDrawWavePixelAsRect(nLineWidth);
    }

    Size testGetWaveLineSize(tools::Long nLineWidth) { return GetWaveLineSize(nLineWidth); }
};

class WaveLineTesterPrinter : public Printer
{
public:
    WaveLineTesterPrinter() {}

    bool AcquireGraphics() const { return true; }
    void ReleaseGraphics(bool) {}
    bool UsePolyPolygonForComplexGradient() { return false; }

    Size testGetWaveLineSize(tools::Long nLineWidth) { return GetWaveLineSize(nLineWidth); }
};
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testShouldDrawWavePixelAsRect)
{
    ScopedVclPtrInstance<WaveLineTester> pTestOutDev;

    CPPUNIT_ASSERT(!pTestOutDev->testShouldDrawWavePixelAsRect(0));
    CPPUNIT_ASSERT(!pTestOutDev->testShouldDrawWavePixelAsRect(1));

    CPPUNIT_ASSERT(pTestOutDev->testShouldDrawWavePixelAsRect(10));
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testGetWaveLineSize)
{
    {
        ScopedVclPtrInstance<WaveLineTester> pTestOutDev;

        pTestOutDev->SetDPIX(96);
        pTestOutDev->SetDPIY(96);

        CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestOutDev->testGetWaveLineSize(0));
        CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestOutDev->testGetWaveLineSize(1));

        CPPUNIT_ASSERT_EQUAL(Size(10, 10), pTestOutDev->testGetWaveLineSize(10));
    }

    {
        ScopedVclPtrInstance<WaveLineTesterPrinter> pTestOutDev;

        pTestOutDev->SetDPIX(96);
        pTestOutDev->SetDPIY(96);

        CPPUNIT_ASSERT_EQUAL(Size(0, 0), pTestOutDev->testGetWaveLineSize(0));
        CPPUNIT_ASSERT_EQUAL(Size(1, 1), pTestOutDev->testGetWaveLineSize(1));

        CPPUNIT_ASSERT_EQUAL(Size(10, 10), pTestOutDev->testGetWaveLineSize(10));
    }
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testErase)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    // this actually triggers Erase()
    pVDev->SetOutputSizePixel(Size(10, 10));
    pVDev->Erase();

    MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (start)", MetaActionType::LINECOLOR,
                                 pAction->GetType());

    pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (start)", MetaActionType::FILLCOLOR,
                                 pAction->GetType());

    pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 2);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action", MetaActionType::RECT, pAction->GetType());

    pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 3);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (end)", MetaActionType::FILLCOLOR,
                                 pAction->GetType());

    pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 4);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action (end)", MetaActionType::LINECOLOR,
                                 pAction->GetType());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawPixel)
{
    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;
        GDIMetaFile aMtf;
        aMtf.Record(pVDev.get());

        // triggers an Erase()
        pVDev->SetOutputSizePixel(Size(10, 10));
        pVDev->SetLineColor(COL_RED);
        pVDev->DrawPixel(Point(0, 0), COL_GREEN);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Color not green", COL_GREEN, pVDev->GetPixel(Point(0, 0)));

        MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a pixel action", MetaActionType::PIXEL,
                                     pAction->GetType());
        MetaPixelAction* pPixelAction = dynamic_cast<MetaPixelAction*>(pAction);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Pixel action has incorrect position", Point(0, 0),
                                     pPixelAction->GetPoint());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Pixel action is wrong color", COL_GREEN,
                                     pPixelAction->GetColor());
    }

    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;
        GDIMetaFile aMtf;
        aMtf.Record(pVDev.get());

        pVDev->SetOutputSizePixel(Size(1, 1));
        pVDev->SetLineColor(COL_RED);
        pVDev->DrawPixel(Point(0, 0));

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Color not red", COL_RED, pVDev->GetPixel(Point(0, 0)));

        MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT + 1);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a point action", MetaActionType::POINT,
                                     pAction->GetType());
        MetaPointAction* pPointAction = dynamic_cast<MetaPointAction*>(pAction);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Pixel action has incorrect position", Point(0, 0),
                                     pPointAction->GetPoint());
    }
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawLine)
{
    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;
        GDIMetaFile aMtf;
        aMtf.Record(pVDev.get());

        pVDev->SetOutputSizePixel(Size(10, 100));
        pVDev->DrawLine(Point(0, 0), Point(0, 50));

        MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line action", MetaActionType::LINE, pAction->GetType());
        MetaLineAction* pLineAction = dynamic_cast<MetaLineAction*>(pAction);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 0),
                                     pLineAction->GetStartPoint());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 50),
                                     pLineAction->GetEndPoint());
    }

    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;
        GDIMetaFile aMtf;
        aMtf.Record(pVDev.get());

        LineInfo aLineInfo(LineStyle::Dash, 10);
        aLineInfo.SetDashCount(5);
        aLineInfo.SetDashLen(10);
        aLineInfo.SetDotCount(3);
        aLineInfo.SetDotLen(13);
        aLineInfo.SetDistance(8);
        aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Bevel);
        aLineInfo.SetLineCap(css::drawing::LineCap_BUTT);

        pVDev->SetOutputSizePixel(Size(100, 100));
        pVDev->DrawLine(Point(0, 0), Point(0, 50), aLineInfo);

        MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line action", MetaActionType::LINE, pAction->GetType());
        MetaLineAction* pLineAction = dynamic_cast<MetaLineAction*>(pAction);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 0),
                                     pLineAction->GetStartPoint());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Line start has incorrect position", Point(0, 50),
                                     pLineAction->GetEndPoint());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash count wrong"static_cast<sal_uInt16>(5),
                                     pLineAction->GetLineInfo().GetDashCount());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Dash len wrong"static_cast<double>(10),
                                     pLineAction->GetLineInfo().GetDashLen());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot count wrong"static_cast<sal_uInt16>(3),
                                     pLineAction->GetLineInfo().GetDotCount());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Dot len wrong"static_cast<double>(13),
                                     pLineAction->GetLineInfo().GetDotLen());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Distance wrong"static_cast<double>(8),
                                     pLineAction->GetLineInfo().GetDistance());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Line join", basegfx::B2DLineJoin::Bevel,
                                     pLineAction->GetLineInfo().GetLineJoin());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Line cap", css::drawing::LineCap_BUTT,
                                     pLineAction->GetLineInfo().GetLineCap());
    }
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawRect)
{
    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;
        GDIMetaFile aMtf;
        aMtf.Record(pVDev.get());

        pVDev->SetOutputSizePixel(Size(100, 100));
        pVDev->DrawRect(tools::Rectangle(Point(0, 0), Size(50, 60)));

        MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action", MetaActionType::RECT, pAction->GetType());
        MetaRectAction* pRectAction = dynamic_cast<MetaRectAction*>(pAction);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Rectangle wrong", tools::Rectangle(Point(0, 0), Size(50, 60)),
                                     pRectAction->GetRect());
    }

    {
        ScopedVclPtrInstance<VirtualDevice> pVDev;
        GDIMetaFile aMtf;
        aMtf.Record(pVDev.get());

        pVDev->SetOutputSizePixel(Size(100, 100));
        pVDev->DrawRect(tools::Rectangle(Point(0, 0), Size(50, 60)), 5, 10);

        MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rect action", MetaActionType::ROUNDRECT,
                                     pAction->GetType());
        MetaRoundRectAction* pRectAction = dynamic_cast<MetaRoundRectAction*>(pAction);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Rectangle wrong", tools::Rectangle(Point(0, 0), Size(50, 60)),
                                     pRectAction->GetRect());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Horizontal round rect wrong"static_cast<sal_uInt32>(5),
                                     pRectAction->GetHorzRound());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Vertical round rect wrong"static_cast<sal_uInt32>(10),
                                     pRectAction->GetVertRound());
    }
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawEllipse)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetOutputSizePixel(Size(100, 100));
    pVDev->DrawEllipse(tools::Rectangle(Point(0, 0), Size(50, 60)));

    MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a ellipse action", MetaActionType::ELLIPSE,
                                 pAction->GetType());
    MetaEllipseAction* pEllipseAction = dynamic_cast<MetaEllipseAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Ellipse rect wrong", tools::Rectangle(Point(0, 0), Size(50, 60)),
                                 pEllipseAction->GetRect());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawPie)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    tools::Rectangle aRect(Point(0, 0), Size(50, 60));

    pVDev->SetOutputSizePixel(Size(100, 100));
    pVDev->DrawPie(aRect, aRect.TopRight(), aRect.TopCenter());

    MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a pie action", MetaActionType::PIE, pAction->GetType());
    MetaPieAction* pPieAction = dynamic_cast<MetaPieAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Pie rect wrong", aRect, pPieAction->GetRect());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Pie start point wrong", aRect.TopRight(),
                                 pPieAction->GetStartPoint());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Pie end point wrong", aRect.TopCenter(),
                                 pPieAction->GetEndPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawChord)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    tools::Rectangle aRect(Point(21, 22), Size(4, 4));
    pVDev->SetOutputSizePixel(Size(100, 100));
    pVDev->DrawChord(aRect, Point(30, 31), Point(32, 33));

    MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a chord action", MetaActionType::CHORD, pAction->GetType());
    MetaChordAction* pChordAction = dynamic_cast<MetaChordAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Chord rect wrong", aRect, pChordAction->GetRect());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Chord start point wrong", Point(30, 31),
                                 pChordAction->GetStartPoint());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Chord end point wrong", Point(32, 33),
                                 pChordAction->GetEndPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawArc)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    tools::Rectangle aRect(Point(1, 2), Size(4, 4));

    pVDev->SetOutputSizePixel(Size(100, 100));
    pVDev->DrawArc(aRect, Point(10, 11), Point(12, 13));

    MetaAction* pAction = aMtf.GetAction(INITIAL_SETUP_ACTION_COUNT);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a arc action", MetaActionType::ARC, pAction->GetType());
    MetaArcAction* pArcAction = dynamic_cast<MetaArcAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Arc rect wrong", aRect, pArcAction->GetRect());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Arc start point wrong", Point(10, 11),
                                 pArcAction->GetStartPoint());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Arc end point wrong", Point(12, 13), pArcAction->GetEndPoint());
}

CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawCheckered)
{
    ScopedVclPtrInstance<VirtualDevice> pVDev;
    GDIMetaFile aMtf;
    aMtf.Record(pVDev.get());

    pVDev->SetOutputSizePixel(Size(100, 100));
    pVDev->DrawCheckered(Point(0, 0), Size(100, 100), 20, COL_BLACK, COL_WHITE);

    size_t nIndex = INITIAL_SETUP_ACTION_COUNT;

    MetaAction* pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not push action", MetaActionType::PUSH, pAction->GetType());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color", MetaActionType::LINECOLOR, pAction->GetType());

    // Row 1
    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 1",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    MetaFillColorAction* pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 1", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not first rect, row 1", MetaActionType::RECT, pAction->GetType());
    MetaRectAction* pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 1 not correct",
                                 tools::Rectangle(Point(0, 0), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 2",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 1", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not second rect, row 1", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 1 not correct",
                                 tools::Rectangle(Point(0, 20), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 3",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 1", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not third rect, row 1", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 1 not correct",
                                 tools::Rectangle(Point(0, 40), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 4",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 4", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not fourth rect, row 1", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 1 not correct",
                                 tools::Rectangle(Point(0, 60), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 1, rect 5",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 1, rect 5", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not fifth rect, row 1", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 1 not correct",
                                 tools::Rectangle(Point(0, 80), Size(21, 21)),
                                 pRectAction->GetRect());

    // Row 2
    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 1",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, first rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 2 not correct",
                                 tools::Rectangle(Point(20, 0), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 2",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, second rect", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 2 not correct",
                                 tools::Rectangle(Point(20, 20), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 3",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 1", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, third rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 2 not correct",
                                 tools::Rectangle(Point(20, 40), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 4",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 4", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, fourth rect", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 2 not correct",
                                 tools::Rectangle(Point(20, 60), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 2, rect 5",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 2, rect 5", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 2, fifth rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 2 not correct",
                                 tools::Rectangle(Point(20, 80), Size(21, 21)),
                                 pRectAction->GetRect());

    // Row 3
    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 1",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 1", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, first rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 3 not correct",
                                 tools::Rectangle(Point(40, 0), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 2",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 1", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, second rect", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 3 not correct",
                                 tools::Rectangle(Point(40, 20), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 3",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 1", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, third rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 3 not correct",
                                 tools::Rectangle(Point(40, 40), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 4",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 4", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, fourth rect", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 3 not correct",
                                 tools::Rectangle(Point(40, 60), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 3, rect 5",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 3, rect 5", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 3, fifth rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 5, row 3 not correct",
                                 tools::Rectangle(Point(40, 80), Size(21, 21)),
                                 pRectAction->GetRect());

    // Row 4
    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 1",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 1", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, first rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 1, row 4 not correct",
                                 tools::Rectangle(Point(60, 0), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 2",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 1", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, second rect", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 2, row 2 not correct",
                                 tools::Rectangle(Point(60, 20), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 3",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 1", COL_BLACK,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, third rect", MetaActionType::RECT, pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 3, row 4 not correct",
                                 tools::Rectangle(Point(60, 40), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 4",
                                 MetaActionType::FILLCOLOR, pAction->GetType());
    pFillColorAction = dynamic_cast<MetaFillColorAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Fill color wrong for row 4, rect 4", COL_WHITE,
                                 pFillColorAction->GetColor());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not row 4, fourth rect", MetaActionType::RECT,
                                 pAction->GetType());
    pRectAction = dynamic_cast<MetaRectAction*>(pAction);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect 4, row 4 not correct",
                                 tools::Rectangle(Point(60, 60), Size(21, 21)),
                                 pRectAction->GetRect());

    nIndex++;
    pAction = aMtf.GetAction(nIndex);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action for row 4, rect 5",
--> --------------------

--> maximum size reached

--> --------------------

95%


¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.23Angebot  Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können  ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.