[Libreoffice-commits] core.git: vcl/backendtest vcl/inc vcl/Library_vcl.mk vcl/qa vcl/skia

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Fri May 22 20:10:36 UTC 2020


 vcl/Library_vcl.mk                    |    1 
 vcl/backendtest/VisualBackendTest.cxx |   43 +++++++++++++++++
 vcl/backendtest/outputdevice/clip.cxx |   83 ++++++++++++++++++++++++++++++++++
 vcl/inc/test/outputdevice.hxx         |   12 ++++
 vcl/qa/cppunit/BackendTest.cxx        |   45 ++++++++++++++++++
 vcl/skia/gdiimpl.cxx                  |   22 +++------
 6 files changed, 191 insertions(+), 15 deletions(-)

New commits:
commit 7f264f4beec931833b390ae1bbb93b2e22b4ad8a
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Fri May 22 18:59:33 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Fri May 22 22:10:00 2020 +0200

    always use region band in Skia's setClipRegion (tdf#133208)
    
    Do like other VCL backends do.
    
    Change-Id: I64b5d5a2fb131b41c70aa63eaf84022e9aa9fab5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94702
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 8e309d24dc86..0e861442218f 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -462,6 +462,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/uitest/uno/uiobject_uno \
     vcl/source/uitest/uno/uitest_uno \
     vcl/backendtest/outputdevice/bitmap \
+    vcl/backendtest/outputdevice/clip \
     vcl/backendtest/outputdevice/common \
     vcl/backendtest/outputdevice/gradient \
     vcl/backendtest/outputdevice/line \
diff --git a/vcl/backendtest/VisualBackendTest.cxx b/vcl/backendtest/VisualBackendTest.cxx
index fb39156714a7..5daa9a642d55 100644
--- a/vcl/backendtest/VisualBackendTest.cxx
+++ b/vcl/backendtest/VisualBackendTest.cxx
@@ -90,7 +90,7 @@ class VisualBackendTestWindow : public WorkWindow
 private:
     Timer maUpdateTimer;
     std::vector<std::chrono::high_resolution_clock::time_point> mTimePoints;
-    static constexpr unsigned char gnNumberOfTests = 8;
+    static constexpr unsigned char gnNumberOfTests = 9;
     unsigned char mnTest;
     bool mbAnimate;
     ScopedVclPtr<VirtualDevice> mpVDev;
@@ -435,6 +435,43 @@ public:
         }
     }
 
+    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)
@@ -534,6 +571,10 @@ public:
             testInvert(rRenderContext, nWidth, nHeight);
         }
         else if (mnTest % gnNumberOfTests == 6)
+        {
+            testClip(rRenderContext, nWidth, nHeight);
+        }
+        else if (mnTest % gnNumberOfTests == 7)
         {
             std::vector<tools::Rectangle> aRegions = setupRegions(3, 1, nWidth, nHeight);
 
diff --git a/vcl/backendtest/outputdevice/clip.cxx b/vcl/backendtest/outputdevice/clip.cxx
new file mode 100644
index 000000000000..86064b583610
--- /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/inc/test/outputdevice.hxx b/vcl/inc/test/outputdevice.hxx
index f2f4784d086c..b6cf70c22bd0 100644
--- a/vcl/inc/test/outputdevice.hxx
+++ b/vcl/inc/test/outputdevice.hxx
@@ -200,6 +200,18 @@ public:
     Bitmap setupRadialGradient();
 };
 
+class VCL_DLLPUBLIC OutputDeviceTestClip : public OutputDeviceTestCommon
+{
+public:
+    Bitmap setupClipRectangle();
+    Bitmap setupClipPolygon();
+    Bitmap setupClipPolyPolygon();
+    Bitmap setupClipB2DPolyPolygon();
+
+    static TestResult checkClip(Bitmap& rBitmap);
+};
+
+
 }} // end namespace vcl::test
 
 #endif
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx
index 7fa586b7049a..b34dda5262ec 100644
--- a/vcl/qa/cppunit/BackendTest.cxx
+++ b/vcl/qa/cppunit/BackendTest.cxx
@@ -455,6 +455,46 @@ public:
             CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
     }
 
+    void testClipRectangle()
+    {
+        vcl::test::OutputDeviceTestClip aOutDevTest;
+        Bitmap aBitmap = aOutDevTest.setupClipRectangle();
+        auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+        exportImage("09-01_clip_rectangle_test.png", aBitmap);
+        if (SHOULD_ASSERT)
+            CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+    }
+
+    void testClipPolygon()
+    {
+        vcl::test::OutputDeviceTestClip aOutDevTest;
+        Bitmap aBitmap = aOutDevTest.setupClipPolygon();
+        auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+        exportImage("09-02_clip_polygon_test.png", aBitmap);
+        if (SHOULD_ASSERT)
+            CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+    }
+
+    void testClipPolyPolygon()
+    {
+        vcl::test::OutputDeviceTestClip aOutDevTest;
+        Bitmap aBitmap = aOutDevTest.setupClipPolyPolygon();
+        auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+        exportImage("09-03_clip_polypolygon_test.png", aBitmap);
+        if (SHOULD_ASSERT)
+            CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+    }
+
+    void testClipB2DPolyPolygon()
+    {
+        vcl::test::OutputDeviceTestClip aOutDevTest;
+        Bitmap aBitmap = aOutDevTest.setupClipB2DPolyPolygon();
+        auto eResult = vcl::test::OutputDeviceTestClip::checkClip(aBitmap);
+        exportImage("09-04_clip_b2dpolypolygon_test.png", aBitmap);
+        if (SHOULD_ASSERT)
+            CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
+    }
+
     void testTdf124848()
     {
         ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
@@ -530,6 +570,11 @@ public:
     CPPUNIT_TEST(testDrawBlend);
     CPPUNIT_TEST(testDrawXor);
 
+    CPPUNIT_TEST(testClipRectangle);
+    CPPUNIT_TEST(testClipPolygon);
+    CPPUNIT_TEST(testClipPolyPolygon);
+    CPPUNIT_TEST(testClipB2DPolyPolygon);
+
     CPPUNIT_TEST(testTdf124848);
 
     CPPUNIT_TEST_SUITE_END();
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 051243ad2a8d..b280f732425f 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -415,20 +415,14 @@ void SkiaSalGraphicsImpl::setCanvasClipRegion(SkCanvas* canvas, const vcl::Regio
 {
     SkiaZone zone;
     SkPath path;
-    // Handle polygons last, since rectangle->polygon area conversions
-    // are problematic (see addPolygonToPath() comment).
-    if (region.getRegionBand())
-    {
-        RectangleVector rectangles;
-        region.GetRegionRectangles(rectangles);
-        for (const tools::Rectangle& rectangle : rectangles)
-            path.addRect(SkRect::MakeXYWH(rectangle.getX(), rectangle.getY(), rectangle.GetWidth(),
-                                          rectangle.GetHeight()));
-    }
-    else if (!region.IsEmpty())
-    {
-        addPolyPolygonToPath(region.GetAsB2DPolyPolygon(), path);
-    }
+    // Always use region rectangles, regardless of what the region uses internally.
+    // That's what other VCL backends do, and trying to use addPolyPolygonToPath()
+    // in case a polygon is used leads to off-by-one errors such as tdf#133208.
+    RectangleVector rectangles;
+    region.GetRegionRectangles(rectangles);
+    for (const tools::Rectangle& rectangle : rectangles)
+        path.addRect(SkRect::MakeXYWH(rectangle.getX(), rectangle.getY(), rectangle.GetWidth(),
+                                      rectangle.GetHeight()));
     path.setFillType(SkPathFillType::kEvenOdd);
     canvas->clipPath(path);
 }


More information about the Libreoffice-commits mailing list