vcl/skia/gdiimpl.cxx |   41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

New commits:
commit 859596233146590f7ebac1f05bbb83ce5ea8aac4
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Sep 18 10:19:33 2020 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Sep 21 14:33:11 2020 +0200

    do not try to merge polygons if they do not share a point (tdf#136222)
    
    If two polygons do not share a point, then they do not share an edge,
    so they cannot be adjacent polygons. As a side-effect this avoids
    the problem with tdf#136222, as it turns out
    basegfx::utils::mergeToSinglePolyPolygon() is broken with polygons
    that are almost but not quite adjacent.
    
    Change-Id: Ibf290cc886d7c337fd04c925b551b2e7773a6b70
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102985
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>
    Tested-by: Jenkins

diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index f6abc2ffb6fb..a5a8b00b9b0c 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -40,6 +40,7 @@
 #include <basegfx/polygon/b2dpolygontools.hxx>
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <o3tl/sorted_vector.hxx>
 
 namespace
 {
@@ -849,6 +850,19 @@ void SkiaSalGraphicsImpl::performDrawPolyPolygon(const 
basegfx::B2DPolyPolygon&
 #endif
 }
 
+namespace
+{
+struct LessThan
+{
+    bool operator()(const basegfx::B2DPoint& point1, const basegfx::B2DPoint& 
point2) const
+    {
+        if (basegfx::fTools::equal(point1.getX(), point2.getX()))
+            return basegfx::fTools::less(point1.getY(), point2.getY());
+        return basegfx::fTools::less(point1.getX(), point2.getX());
+    }
+};
+} // namespace
+
 bool SkiaSalGraphicsImpl::delayDrawPolyPolygon(const basegfx::B2DPolyPolygon& 
aPolyPolygon,
                                                double fTransparency)
 {
@@ -877,6 +891,9 @@ bool SkiaSalGraphicsImpl::delayDrawPolyPolygon(const 
basegfx::B2DPolyPolygon& aP
     // so they do not need joining.
     if (aPolyPolygon.count() != 1)
         return false;
+    // If the polygon is not closed, it doesn't mark an area to be filled.
+    if (!aPolyPolygon.isClosed())
+        return false;
     // If a polygon does not contain a straight line, i.e. it's all curves, 
then do not merge.
     // First of all that's even more expensive, and second it's very unlikely 
that it's a polygon
     // split into more polygons.
@@ -889,6 +906,28 @@ bool SkiaSalGraphicsImpl::delayDrawPolyPolygon(const 
basegfx::B2DPolyPolygon& aP
     {
         checkPendingDrawing(); // Cannot be parts of the same larger polygon, 
draw the last and reset.
     }
+    if (!mLastPolyPolygonInfo.polygons.empty())
+    {
+        assert(aPolyPolygon.count() == 1);
+        assert(mLastPolyPolygonInfo.polygons.back().count() == 1);
+        // Check if the new and the previous polygon share at least one point. 
If not, then they
+        // cannot be adjacent polygons, so there's no point in trying to merge 
them.
+        bool sharePoint = false;
+        const basegfx::B2DPolygon& poly1 = aPolyPolygon.getB2DPolygon(0);
+        const basegfx::B2DPolygon& poly2 = 
mLastPolyPolygonInfo.polygons.back().getB2DPolygon(0);
+        o3tl::sorted_vector<basegfx::B2DPoint, LessThan> poly1Points; // for 
O(n log n)
+        poly1Points.reserve(poly1.count());
+        for (sal_uInt32 i = 0; i < poly1.count(); ++i)
+            poly1Points.insert(poly1.getB2DPoint(i));
+        for (sal_uInt32 i = 0; i < poly2.count(); ++i)
+            if (poly1Points.find(poly2.getB2DPoint(i)) != poly1Points.end())
+            {
+                sharePoint = true;
+                break;
+            }
+        if (!sharePoint)
+            checkPendingDrawing(); // Draw the previous one and reset.
+    }
     // Collect the polygons that can be possibly merged. Do the merging only 
once at the end,
     // because it's not a cheap operation.
     mLastPolyPolygonInfo.polygons.push_back(aPolyPolygon);
@@ -908,6 +947,8 @@ void SkiaSalGraphicsImpl::checkPendingDrawing()
         if (polygons.size() == 1)
             performDrawPolyPolygon(polygons.front(), transparency, true);
         else
+            // TODO: tdf#136222 shows that 
basegfx::utils::mergeToSinglePolyPolygon() is unreliable
+            // in corner cases, possibly either a bug or rounding errors 
somewhere.
             
performDrawPolyPolygon(basegfx::utils::mergeToSinglePolyPolygon(polygons), 
transparency,
                                    true);
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to