Files
wx_wherigo/libs/wxWidgets-3.3.1/tests/graphics/clipper.cpp
2026-02-14 09:47:24 +01:00

758 lines
17 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: tests/graphics/clipper.cpp
// Purpose: wxDCClipper unit tests
// Author: Artur Wieczorek
// Created: 2022-12-27
// Copyright: (c) 2022 wxWidgets development team
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#include <memory>
#include "wx/bitmap.h"
#include "wx/dcclient.h"
#include "wx/dcgraph.h"
#include "wx/dcmemory.h"
#include "wx/dcsvg.h"
#include "wx/app.h"
#include "wx/window.h"
#include "testfile.h"
#include "waitfor.h"
static const wxSize s_dcSize(260, 300);
static inline wxRect DeviceToLogical(wxDC& dc, const wxRect& r)
{
return wxRect(dc.DeviceToLogical(r.GetPosition()), dc.DeviceToLogicalRel(r.GetSize()));
}
static void NoTransform(wxDC& dc)
{
wxRect initClipBox;
dc.GetClippingBox(initClipBox);
{
const wxRect r(10, 20, 30, 40);
wxDCClipper clipper(dc, r);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(r == clipBox);
}
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(initClipBox == clipBox);
}
static void ExternalTransform(wxDC& dc, bool useTransformMatrix)
{
#if wxUSE_DC_TRANSFORM_MATRIX
if ( useTransformMatrix && !dc.CanUseTransformMatrix() )
return;
#endif // wxUSE_DC_TRANSFORM_MATRIX
#if wxUSE_DC_TRANSFORM_MATRIX
if ( useTransformMatrix )
{
wxAffineMatrix2D m;
m.Translate(40, 75);
m.Scale(2.0, 3.0);
dc.SetTransformMatrix(m);
}
else
#endif // wxUSE_DC_TRANSFORM_MATRIX
{
dc.SetDeviceOrigin(10, 15);
dc.SetUserScale(0.5, 1.5);
dc.SetLogicalScale(4.0, 2.0);
dc.SetLogicalOrigin(-15, -20);
}
wxRect initClipBox;
dc.GetClippingBox(initClipBox);
{
const wxRect r(10, 20, 30, 40);
wxDCClipper clipper(dc, r);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(r == clipBox);
}
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(initClipBox == clipBox);
}
static void InternalTransform(wxDC& dc, bool useTransformMatrix)
{
#if wxUSE_DC_TRANSFORM_MATRIX
if ( useTransformMatrix && !dc.CanUseTransformMatrix() )
return;
#endif // wxUSE_DC_TRANSFORM_MATRIX
wxRect initClipBox;
dc.GetClippingBox(initClipBox);
{
const wxRect r(10, 20, 30, 40);
wxDCClipper clipper(dc, r);
#if wxUSE_DC_TRANSFORM_MATRIX
if ( useTransformMatrix )
{
wxAffineMatrix2D m;
m.Translate(40, 75);
m.Scale(2.0, 3.0);
dc.SetTransformMatrix(m);
}
else
#endif // wxUSE_DC_TRANSFORM_MATRIX
{
dc.SetDeviceOrigin(10, 15);
dc.SetUserScale(0.5, 1.5);
dc.SetLogicalScale(4.0, 2.0);
dc.SetLogicalOrigin(-15, -20);
}
wxRect clipExpected = DeviceToLogical(dc, r);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(clipExpected == clipBox);
}
wxRect initClipExpected = DeviceToLogical(dc, initClipBox);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(initClipExpected == clipBox);
}
static void SpecificClipping(wxDC& dc)
{
wxRect initClipBox;
dc.GetClippingBox(initClipBox);
{
const wxRect r(10, 20, 30, 40);
wxDCClipper clipper(dc, r);
const wxRect r1(16, 25, 20, 30);
dc.SetClippingRegion(r1);
wxRect clipExpected = DeviceToLogical(dc, r1);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(clipExpected == clipBox);
}
wxRect initClipExpected = DeviceToLogical(dc, initClipBox);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(initClipExpected == clipBox);
}
static void InternalTransformSpecificClipping(wxDC& dc, bool useTransformMatrix)
{
#if wxUSE_DC_TRANSFORM_MATRIX
if ( useTransformMatrix && !dc.CanUseTransformMatrix() )
return;
#endif // wxUSE_DC_TRANSFORM_MATRIX
wxRect initClipBox;
dc.GetClippingBox(initClipBox);
{
const wxRect r(10, 20, 30, 40);
wxDCClipper clipper(dc, r);
const wxRect r1(16, 25, 20, 30);
dc.SetClippingRegion(r1);
#if wxUSE_DC_TRANSFORM_MATRIX
if ( useTransformMatrix )
{
wxAffineMatrix2D m;
m.Translate(40, 75);
m.Scale(2.0, 3.0);
dc.SetTransformMatrix(m);
}
else
#endif // wxUSE_DC_TRANSFORM_MATRIX
{
dc.SetDeviceOrigin(10, 15);
dc.SetUserScale(0.5, 1.5);
dc.SetLogicalScale(4.0, 2.0);
dc.SetLogicalOrigin(-15, -20);
}
wxRect clipExpected = DeviceToLogical(dc, r1);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(clipExpected == clipBox);
}
wxRect initClipExpected = DeviceToLogical(dc, initClipBox);
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(initClipExpected == clipBox);
}
static void NoTransformEmbeddedClip(wxDC& dc)
{
wxRect initClipBox;
dc.GetClippingBox(initClipBox);
{
const wxRect r1(10, 20, 30, 40);
wxDCClipper clipper1(dc, r1);
{
const wxRect r2(15, 25, 20, 30);
wxDCClipper clipper2(dc, r2);
wxRect clipBox2;
dc.GetClippingBox(clipBox2);
CHECK(r2 == clipBox2);
}
wxRect clipBox1;
dc.GetClippingBox(clipBox1);
CHECK(r1 == clipBox1);
}
wxRect clipBox;
dc.GetClippingBox(clipBox);
CHECK(initClipBox == clipBox);
}
static void DCAttributes(wxDC& dc)
{
// Check if wxDC atrributes left unchanged
wxFont font = dc.GetFont().Bold().Smaller();
wxPen pen(*wxYELLOW, 2);
wxBrush brush = *wxBLUE_BRUSH;
wxDCFontChanger fontChanger(dc, font);
wxDCPenChanger penChanger(dc,pen);
wxDCBrushChanger brushChanger(dc, brush);
wxCoord chWidth = dc.GetCharWidth();
wxCoord chHeight = dc.GetCharHeight();
wxFontMetrics fm = dc.GetFontMetrics();
{
wxDCClipper clipper(dc, 10, 20, 30, 40);
}
CHECK(dc.GetFont() == font);
CHECK(dc.GetPen() == pen);
CHECK(dc.GetBrush() == brush);
CHECK(dc.GetCharWidth() == chWidth);
CHECK(dc.GetCharHeight() == chHeight);
wxFontMetrics fm2 = dc.GetFontMetrics();
CHECK(fm2.ascent == fm.ascent);
CHECK(fm2.averageWidth == fm.averageWidth);
CHECK(fm2.descent == fm.descent);
CHECK(fm2.externalLeading == fm.externalLeading);
CHECK(fm2.height == fm.height);
CHECK(fm2.internalLeading == fm.internalLeading);
}
TEST_CASE("ClipperTestCase::wxDC", "[clipper][dc]")
{
wxBitmap bmp(s_dcSize);
wxMemoryDC dc(bmp);
dc.SetBackground(*wxWHITE_BRUSH);
dc.Clear();
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
}
#if wxUSE_GRAPHICS_CONTEXT
TEST_CASE("ClipperTestCase::wxGCDC", "[clipper][dc][gcdc]")
{
#ifdef __WXMSW__
int depth = GENERATE(24, 32);
wxBitmap bmp(s_dcSize, depth);
#else
wxBitmap bmp(s_dcSize);
#endif
wxMemoryDC mdc(bmp);
mdc.SetBackground(*wxWHITE_BRUSH);
mdc.Clear();
wxGCDC dc(mdc);
dc.GetGraphicsContext()->SetAntialiasMode(wxANTIALIAS_NONE);
dc.GetGraphicsContext()->DisableOffset();
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
}
#ifdef __WXMSW__
#if wxUSE_GRAPHICS_GDIPLUS
TEST_CASE("ClipperTestCase::wxGCDC(GDI+)", "[clipper][dc][gcdc][gdiplus]")
{
int depth = GENERATE(24, 32);
wxBitmap bmp(s_dcSize, depth);
wxMemoryDC mdc(bmp);
mdc.SetBackground(*wxWHITE_BRUSH);
mdc.Clear();
wxGraphicsRenderer* rend = wxGraphicsRenderer::GetGDIPlusRenderer();
REQUIRE(rend);
wxGraphicsContext* gc = rend->CreateContext(mdc);
gc->SetAntialiasMode(wxANTIALIAS_NONE);
gc->DisableOffset();
wxGCDC dc(gc);
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
}
#endif // wxUSE_GRAPHICS_GDIPLUS
#if wxUSE_GRAPHICS_DIRECT2D
TEST_CASE("ClipperTestCase::wxGCDC(Direct2D)", "[clipper][dc][gcdc][direct2d]")
{
if ( wxIsRunningUnderWine() )
{
WARN("Skipping tests known to fail in Wine");
}
else
{
int depth = GENERATE(24, 32);
wxBitmap bmp(s_dcSize, depth);
wxMemoryDC mdc(bmp);
mdc.SetBackground(*wxWHITE_BRUSH);
mdc.Clear();
wxGraphicsRenderer* rend = wxGraphicsRenderer::GetDirect2DRenderer();
REQUIRE(rend);
wxGraphicsContext* gc = rend->CreateContext(mdc);
gc->SetAntialiasMode(wxANTIALIAS_NONE);
gc->DisableOffset();
wxGCDC dc(gc);
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
}
}
#endif // wxUSE_GRAPHICS_DIRECT2D
#endif // __WXMSW__
#if wxUSE_CAIRO
TEST_CASE("ClipperTestCase::wxGCDC(Cairo)", "[clipper][dc][gcdc][cairo]")
{
#ifdef __WXMSW__
int depth = GENERATE(24, 32);
wxBitmap bmp(s_dcSize, depth);
#else
wxBitmap bmp(s_dcSize);
#endif
wxMemoryDC mdc(bmp);
mdc.SetBackground(*wxWHITE_BRUSH);
mdc.Clear();
wxGraphicsRenderer* rend = wxGraphicsRenderer::GetCairoRenderer();
REQUIRE(rend);
wxGraphicsContext* gc = rend->CreateContext(mdc);
gc->SetAntialiasMode(wxANTIALIAS_NONE);
gc->DisableOffset();
wxGCDC dc(gc);
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
}
#endif // wxUSE_CAIRO
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_SVG
TEST_CASE("ClipperTestCase::wxSVGFileDC", "[clipper][dc][svgdc]")
{
TestFile tf;
wxSVGFileDC dc(tf.GetName(), s_dcSize.x, s_dcSize.y);
dc.SetBackground(*wxWHITE_BRUSH);
dc.Clear();
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
}
#endif // wxUSE_SVG
TEST_CASE("ClipperTestCase::wxPaintDC", "[clipper][dc][paintdc]")
{
// Ensure window is shown and large enough for testing
wxTheApp->GetTopWindow()->Raise();
REQUIRE(wxTheApp->GetTopWindow()->IsShown());
wxSize winSize = wxTheApp->GetTopWindow()->GetSize();
winSize.x = wxMax(winSize.x, s_dcSize.x + 50);
winSize.y = wxMax(winSize.y, s_dcSize.y + 50);
wxTheApp->GetTopWindow()->SetSize(winSize);
#if defined(__WXGTK__)
// Under wxGTK we need to have two children (at least) because if there
// is one child its paint area is set to fill the whole parent frame.
std::unique_ptr<wxWindow> w0(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY));
#endif // wxGTK
std::unique_ptr<wxWindow> win(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY, wxPoint(0, 0)));
win->SetClientSize(s_dcSize);
// Wait for the first paint event to be sure
// that window really has its final size.
wxWindow* testWin = win.get();
{
WaitForPaint waitForPaint(testWin);
testWin->Show();
waitForPaint.YieldUntilPainted();
}
bool paintExecuted = false;
testWin->Bind(wxEVT_PAINT, [=, &paintExecuted](wxPaintEvent&)
{
wxPaintDC dc(testWin);
REQUIRE(dc.GetSize() == s_dcSize);
dc.SetBackground(*wxWHITE_BRUSH);
dc.Clear();
SECTION("NoTransform")
{
NoTransform(dc);
}
SECTION("ExternalTransform 1")
{
ExternalTransform(dc, false);
}
SECTION("ExternalTransform 2")
{
ExternalTransform(dc, true);
}
SECTION("InternalTransform 1")
{
InternalTransform(dc, false);
}
SECTION("InternalTransform 2")
{
InternalTransform(dc, true);
}
SECTION("SpecificClipping")
{
SpecificClipping(dc);
}
SECTION("InternalTransformSpecificClipping 1")
{
InternalTransformSpecificClipping(dc, false);
}
SECTION("InternalTransformSpecificClipping 2")
{
InternalTransformSpecificClipping(dc, true);
}
SECTION("NoTransformEmbeddedClip")
{
NoTransformEmbeddedClip(dc);
}
SECTION("DCAttributes")
{
DCAttributes(dc);
}
paintExecuted = true;
});
testWin->Refresh();
testWin->Update();
// Wait for update to be done
YieldForAWhile();
CHECK(paintExecuted == true);
}