sw/inc/swregion.hxx                |   20 +++++++++++++++++---
 sw/source/core/bastyp/swregion.cxx |   15 +++++++++++++--
 sw/source/core/crsr/viscrs.cxx     |    6 +++---
 sw/source/core/view/viewimp.cxx    |    5 +++--
 sw/source/core/view/viewsh.cxx     |    7 ++-----
 5 files changed, 38 insertions(+), 15 deletions(-)

New commits:
commit ceb75179b2a310ffe5bfbb629fabff7f34406bec
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Sep 17 00:22:49 2021 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Sun Sep 19 09:33:35 2021 +0200

    do not double-invert SwRegionRects
    
    The usual way to use SwRegionRects seems to be to set it to the full
    area (origin) and then use operator-= to remove parts. But operator-=
    is slower than operator+=, so if that all is followed by Invert()
    and Compress(), it's essentially inverting the operation twice,
    making it both slower and (IMO) more complicated. Make it possible
    to simply use operator+=, collect all rectangles and then
    post-process once using LimitToOrigin()+Compress().
    
    I'm not entirely happy about the SwRegionRects constructor, but
    I don't have a better idea that wouldn't silently break backwards
    compatibility for backporting.
    
    Change-Id: If3c83e32729e5d02b9d97b66c93fac04d4fb3ecc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122217
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/sw/inc/swregion.hxx b/sw/inc/swregion.hxx
index 7ba3ffdee024..1aa190712a8f 100644
--- a/sw/inc/swregion.hxx
+++ b/sw/inc/swregion.hxx
@@ -25,22 +25,36 @@
 
 typedef std::vector<SwRect> SwRects;
 
+// A collection of rectangles within a given area (origin).
+// One way to use is to initially set rStartRect, which will set the origin
+// and the rectangles to rStartRect, and then use operator-= to punch holes.
+// Other way to use is to use empty constructor, call ChangeOrigin() and
+// then use operator+= to add rectangles, possibly followed by final
+// LimitToOrigin() and Compress(). The second way should be faster than
+// the first way followed by Invert().
 class SwRegionRects : public SwRects
 {
-    SwRect m_aOrigin; // Copy of StartRect.
+    SwRect m_aOrigin; // Origin area, limits the total area e.g. for Invert()
 
     inline void InsertRect( const SwRect &rRect, const sal_uInt16 nPos, bool 
&rDel);
 
 public:
-    SwRegionRects( const SwRect& rStartRect, sal_uInt16 nInit = 20 );
+    // Sets rStartRect as the first element and also the origin area.
+    explicit SwRegionRects( const SwRect& rStartRect, sal_uInt16 nInit = 20 );
+    // Empty constructor, does not set elements or origin area. You may
+    // most likely want to call ChangeOrigin() afterwards.
+    explicit SwRegionRects( sal_uInt16 nInit = 20 );
 
     // For punching from aOrigin.
     void operator-=( const SwRect& rRect );
     void operator+=( const SwRect& rRect );
 
-    // From holes to areas, from areas to holes.
+    // From holes to areas, from areas to holes, within the origin area.
     void Invert();
 
+    // Ensures all rectangles are within the origin area.
+    void LimitToOrigin();
+
     // Combine adjacent rectangles.
     void Compress();
 
diff --git a/sw/source/core/bastyp/swregion.cxx 
b/sw/source/core/bastyp/swregion.cxx
index 55b857ffdefa..a54f9e4bddec 100644
--- a/sw/source/core/bastyp/swregion.cxx
+++ b/sw/source/core/bastyp/swregion.cxx
@@ -29,6 +29,12 @@ SwRegionRects::SwRegionRects( const SwRect &rStartRect, 
sal_uInt16 nInit ) :
     push_back( m_aOrigin );
 }
 
+SwRegionRects::SwRegionRects( sal_uInt16 nInit ) :
+    m_aOrigin()
+{
+    reserve(nInit);
+}
+
 // If <rDel> is true then this Rect will be overwritten by <rRect> at
 // position <nPos>. Otherwise <rRect> is attached at the end.
 inline void SwRegionRects::InsertRect( const SwRect &rRect,
@@ -47,8 +53,7 @@ inline void SwRegionRects::InsertRect( const SwRect &rRect,
 
 void SwRegionRects::operator+=( const SwRect &rRect )
 {
-    bool f = false;
-    InsertRect( rRect, 0, f );
+    push_back( rRect );
 }
 
 /** Delete all overlaps of the Rects in array with the given <rRect>
@@ -141,6 +146,12 @@ static inline SwTwips CalcArea( const SwRect &rRect )
     return rRect.Width() * rRect.Height();
 }
 
+void SwRegionRects::LimitToOrigin()
+{
+    for (size_type i = 0; i < size(); ++i )
+        (*this)[ i ].Intersection( m_aOrigin );
+}
+
 // combine all adjacent rectangles
 void SwRegionRects::Compress()
 {
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 92dbbdb29f49..b664e5f6c80b 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -839,9 +839,9 @@ void SwShellTableCursor::FillRects()
         return;
 
     bool bStart = true;
-    SwRegionRects aReg( GetShell()->VisArea() );
-    if (comphelper::LibreOfficeKit::isActive())
-        aReg = 
GetShell()->getIDocumentLayoutAccess().GetCurrentLayout()->getFrameArea();
+    SwRegionRects aReg( comphelper::LibreOfficeKit::isActive()
+        ? 
GetShell()->getIDocumentLayoutAccess().GetCurrentLayout()->getFrameArea()
+        : GetShell()->VisArea() );
     SwNodes& rNds = GetDoc().GetNodes();
     SwFrame* pEndFrame = nullptr;
     for (size_t n = 0; n < m_SelectedBoxes.size(); ++n)
diff --git a/sw/source/core/view/viewimp.cxx b/sw/source/core/view/viewimp.cxx
index 317480500eac..92bde3c9bab5 100644
--- a/sw/source/core/view/viewimp.cxx
+++ b/sw/source/core/view/viewimp.cxx
@@ -128,9 +128,10 @@ bool SwViewShellImp::AddPaintRect( const SwRect &rRect )
             // In case of normal rendering, this makes sure only visible 
rectangles are painted.
             // Otherwise get the rectangle of the full document, so all paint 
rectangles are invalidated.
             const SwRect& rArea = comphelper::LibreOfficeKit::isActive() ? 
m_pShell->GetLayout()->getFrameArea() : m_pShell->VisArea();
-            m_pRegion.reset(new SwRegionRects(rArea));
+            m_pRegion.reset(new SwRegionRects);
+            m_pRegion->ChangeOrigin(rArea);
         }
-        (*m_pRegion) -= rRect;
+        (*m_pRegion) += rRect;
         return true;
     }
     return false;
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 4276b4161482..7e0fe1980006 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -327,9 +327,7 @@ void SwViewShell::ImplEndAction( const bool bIdleEnd )
             {
                 SwRootFrame* pCurrentLayout = GetLayout();
 
-                //First Invert then Compress, never the other way round!
-                pRegion->Invert();
-
+                pRegion->LimitToOrigin();
                 pRegion->Compress();
 
                 ScopedVclPtr<VirtualDevice> pVout;
@@ -1665,8 +1663,7 @@ bool SwViewShell::CheckInvalidForPaint( const SwRect 
&rRect )
 
         if ( pRegion )
         {
-            //First Invert then Compress, never the other way round!
-            pRegion->Invert();
+            pRegion->LimitToOrigin();
             pRegion->Compress();
             bRet = false;
             if ( !pRegion->empty() )

Reply via email to