svx/source/sdr/overlay/overlayselection.cxx |  233 +++++++---------------------
 1 file changed, 60 insertions(+), 173 deletions(-)

New commits:
commit 302a221856809e2b046cb9fb1675bfff4d86a37d
Author:     Noel Grandin <[email protected]>
AuthorDate: Thu May 30 13:31:28 2024 +0200
Commit:     Noel Grandin <[email protected]>
CommitDate: Sat Jun 1 10:22:55 2024 +0200

    tdf#161198 tdf#161322 fix selection overlays
    
    revert
        commit 7b1405689d4246e0e37e8759f03e1962af964cec
        Author: Noel Grandin <[email protected]>
        Date:   Fri Apr 19 22:56:04 2024 +0200
        reduce the number of drawing primitives we create in
        OverlaySelection
    
    Change-Id: I868540aadb3a75582990ae4491807991617215b1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168253
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <[email protected]>

diff --git a/svx/source/sdr/overlay/overlayselection.cxx 
b/svx/source/sdr/overlay/overlayselection.cxx
index a5598c1d2125..49418ae906e9 100644
--- a/svx/source/sdr/overlay/overlayselection.cxx
+++ b/svx/source/sdr/overlay/overlayselection.cxx
@@ -34,137 +34,31 @@
 #include <o3tl/sorted_vector.hxx>
 #include <map>
 
-namespace
-{
-struct B2DPointCompare
-{
-    bool operator()(const basegfx::B2DPoint& lhs, const basegfx::B2DPoint& 
rhs) const
-    {
-        return std::make_pair(lhs.getX(), lhs.getY()) < 
std::make_pair(rhs.getX(), rhs.getY());
-    }
-};
-
-struct B2DPointCompareYThenX
-{
-    bool operator()(const basegfx::B2DPoint& lhs, const basegfx::B2DPoint& 
rhs) const
-    {
-        return std::make_pair(lhs.getY(), lhs.getX()) < 
std::make_pair(rhs.getY(), rhs.getX());
-    }
-};
-
-}
-
 namespace sdr::overlay
 {
 
-    // Combine rectangles geometrically to a single OR'ed polygon.
-    // Algorithm is from
-    //     "Uniqueness of orthogonal connect-the-dots" Joseph O'Rourke 1988
-    // The basic algorithm is:
-    //   Sort points by lowest x, lowest y
-    //   Go through each column and create edges between the vertices 2i and 
2i + 1 in that column
-    //   Sort points by lowest y, lowest x
-    //   Go through each row and create edges between the vertices 2i and 2i + 
1 in that row.
-    //
-    static basegfx::B2DPolyPolygon impCombineRectanglesToPolyPolygon(const 
std::vector< basegfx::B2DRange >& rRectangles)
-    {
-        o3tl::sorted_vector<basegfx::B2DPoint, B2DPointCompare> sort_x;
-        for (auto const & rRect : rRectangles)
+        // combine rages geometrically to a single, ORed polygon
+        static basegfx::B2DPolyPolygon impCombineRangesToPolyPolygon(const 
std::vector< basegfx::B2DRange >& rRanges)
         {
-            auto checkPoint = [&sort_x](double x, double y)
-            {
-                basegfx::B2DPoint pt(x, y);
-                auto it = sort_x.find(pt);
-                if (it != sort_x.end()) // Shared vertice, remove it.
-                    sort_x.erase(it);
-                else
-                    sort_x.insert(pt);
-            };
-            checkPoint(rRect.getMinX(), rRect.getMinY());
-            checkPoint(rRect.getMinX(), rRect.getMaxY());
-            checkPoint(rRect.getMaxX(), rRect.getMinY());
-            checkPoint(rRect.getMaxX(), rRect.getMaxY());
-        }
-
-
-        o3tl::sorted_vector<basegfx::B2DPoint, B2DPointCompareYThenX> sort_y;
-        for (auto const & i : sort_x)
-            sort_y.insert(i);
-
-        std::map<basegfx::B2DPoint, basegfx::B2DPoint, B2DPointCompare> 
edges_h;
-        std::map<basegfx::B2DPoint, basegfx::B2DPoint, B2DPointCompare> 
edges_v;
+            const sal_uInt32 nCount(rRanges.size());
+            basegfx::B2DPolyPolygon aRetval;
 
-        size_t i = 0;
-        while (i < sort_x.size())
-        {
-            auto curr_y = sort_y[i].getY();
-            while (i < sort_x.size() && sort_y[i].getY() == curr_y)
-            {
-                edges_h[sort_y[i]] = sort_y[i + 1];
-                edges_h[sort_y[i + 1]] = sort_y[i];
-                i += 2;
-            }
-        }
-        i = 0;
-        while (i < sort_x.size())
-        {
-            auto curr_x = sort_x[i].getX();
-            while (i < sort_x.size() && sort_x[i].getX() == curr_x)
+            for(sal_uInt32 a(0); a < nCount; a++)
             {
-                edges_v[sort_x[i]] = sort_x[i + 1];
-                edges_v[sort_x[i + 1]] = sort_x[i];
-                i += 2;
-            }
-        }
+                const basegfx::B2DPolygon 
aDiscretePolygon(basegfx::utils::createPolygonFromRect(rRanges[a]));
 
-        // Get all the polygons.
-        basegfx::B2DPolyPolygon aPolyPolygon;
-        std::vector<std::tuple<basegfx::B2DPoint, bool>> tmpPolygon;
-        while (!edges_h.empty())
-        {
-            tmpPolygon.clear();
-            // We can start with any point.
-            basegfx::B2DPoint pt = edges_h.begin()->first;
-            edges_h.erase(edges_h.begin());
-            tmpPolygon.push_back({pt, false});
-            for (;;)
-            {
-                auto [curr, e] = tmpPolygon.back();
-                if (!e)
+                if(0 == a)
                 {
-                    auto it = edges_v.find(curr);
-                    auto next_vertex = it->second;
-                    edges_v.erase(it);
-                    tmpPolygon.push_back({next_vertex, true});
+                    aRetval.append(aDiscretePolygon);
                 }
                 else
                 {
-                    auto it = edges_h.find(curr);
-                    auto next_vertex = it->second;
-                    edges_h.erase(it);
-                    tmpPolygon.push_back({next_vertex, false});
-                }
-                if (tmpPolygon.back() == tmpPolygon.front())
-                {
-                    // Closed polygon
-                    break;
+                    aRetval = basegfx::utils::solvePolygonOperationOr(aRetval, 
basegfx::B2DPolyPolygon(aDiscretePolygon));
                 }
             }
-            for (auto const & pair : tmpPolygon)
-            {
-                auto const & vertex = std::get<0>(pair);
-                edges_h.erase(vertex);
-                edges_v.erase(vertex);
-            }
-            basegfx::B2DPolygon aPoly;
-            aPoly.reserve(tmpPolygon.size());
-            for (auto const & pair : tmpPolygon)
-                aPoly.append(std::get<0>(pair));
-            aPolyPolygon.append(std::move(aPoly));
-        }
 
-        return aPolyPolygon;
-    }
+            return aRetval;
+        }
 
         // check if wanted type OverlayType::Transparent or OverlayType::Solid
         // is possible. If not, fallback to invert mode (classic mode)
@@ -200,70 +94,63 @@ namespace sdr::overlay
         drawinglayer::primitive2d::Primitive2DContainer 
OverlaySelection::createOverlayObjectPrimitive2DSequence()
         {
             drawinglayer::primitive2d::Primitive2DContainer aRetval;
-            const sal_uInt32 nCount(maRanges.size());
-
-            if(!nCount)
-                return aRetval;
+            const sal_uInt32 nCount(getRanges().size());
 
-            // create range primitives
-            const bool bInvert(OverlayType::Invert == maLastOverlayType);
-            basegfx::BColor aRGBColor(getBaseColor().getBColor());
-            if(bInvert)
+            if(nCount)
             {
-                // force color to white for invert to get a full invert
-                aRGBColor = basegfx::BColor(1.0, 1.0, 1.0);
-            }
-
-            aRetval.resize(nCount);
-            for(sal_uInt32 a(0);a < nCount; a++)
-            {
-                basegfx::B2DPolygon 
aPolygon(basegfx::utils::createPolygonFromRect(maRanges[a]));
-                aRetval[a] =
-                    new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
-                        basegfx::B2DPolyPolygon(std::move(aPolygon)),
-                        aRGBColor);
-            }
-
-            basegfx::B2DPolyPolygon aPolyPolygon;
-            aPolyPolygon.reserve(nCount);
-            for(sal_uInt32 a(0);a < nCount; a++)
-                
aPolyPolygon.append(basegfx::utils::createPolygonFromRect(maRanges[a]));
-            aRetval.append(
-                new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
-                    std::move(aPolyPolygon),
-                    aRGBColor));
+                // create range primitives
+                const bool bInvert(OverlayType::Invert == maLastOverlayType);
+                basegfx::BColor aRGBColor(getBaseColor().getBColor());
+                aRetval.resize(nCount);
 
-            if(bInvert)
-            {
-                // embed all in invert primitive
-                aRetval = drawinglayer::primitive2d::Primitive2DContainer {
-                        new drawinglayer::primitive2d::InvertPrimitive2D(
-                            std::move(aRetval))
-                };
-            }
-            else if(OverlayType::Transparent == maLastOverlayType)
-            {
-                // embed all rectangles in transparent paint
-                const double fTransparence(mnLastTransparence / 100.0);
-                drawinglayer::primitive2d::Primitive2DReference 
aUnifiedTransparence(
-                    new 
drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
-                        std::move(aRetval),
-                        fTransparence));
+                if(bInvert)
+                {
+                    // force color to white for invert to get a full invert
+                    aRGBColor = basegfx::BColor(1.0, 1.0, 1.0);
+                }
 
-                if(mbBorder)
+                for(sal_uInt32 a(0);a < nCount; a++)
                 {
-                    drawinglayer::primitive2d::Primitive2DReference 
aSelectionOutline(
-                        new 
drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
-                            impCombineRectanglesToPolyPolygon(maRanges),
-                            aRGBColor));
+                    const basegfx::B2DPolygon 
aPolygon(basegfx::utils::createPolygonFromRect(maRanges[a]));
+                    aRetval[a] =
+                        new 
drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+                            basegfx::B2DPolyPolygon(aPolygon),
+                            aRGBColor);
+                }
 
-                    // add both to result
-                    aRetval = drawinglayer::primitive2d::Primitive2DContainer 
{ aUnifiedTransparence, aSelectionOutline };
+                if(bInvert)
+                {
+                    // embed all in invert primitive
+                    aRetval = drawinglayer::primitive2d::Primitive2DContainer {
+                            new drawinglayer::primitive2d::InvertPrimitive2D(
+                                std::move(aRetval))
+                    };
                 }
-                else
+                else if(OverlayType::Transparent == maLastOverlayType)
                 {
-                    // just add transparent part
-                    aRetval = drawinglayer::primitive2d::Primitive2DContainer 
{ aUnifiedTransparence };
+                    // embed all rectangles in transparent paint
+                    const double fTransparence(mnLastTransparence / 100.0);
+                    const drawinglayer::primitive2d::Primitive2DReference 
aUnifiedTransparence(
+                        new 
drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+                            std::move(aRetval),
+                            fTransparence));
+
+                    if(mbBorder)
+                    {
+                        basegfx::B2DPolyPolygon 
aPolyPolygon(impCombineRangesToPolyPolygon(getRanges()));
+                        const drawinglayer::primitive2d::Primitive2DReference 
aSelectionOutline(
+                            new 
drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
+                                std::move(aPolyPolygon),
+                                aRGBColor));
+
+                        // add both to result
+                        aRetval = 
drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence, 
aSelectionOutline };
+                    }
+                    else
+                    {
+                        // just add transparent part
+                        aRetval = 
drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence };
+                    }
                 }
             }
 

Reply via email to