summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-09-17 00:22:49 +0200
committerLuboš Luňák <l.lunak@collabora.com>2021-09-19 09:32:48 +0200
commit5a3c60f7c76fc0eca21f0fd468783e0ae48e3129 (patch)
tree807867659a2d1b3cbefac65d6753db471d36fee1
parentbc09e2c08f9db85c8f1cbd9c0e71e3e60d6d6ed3 (diff)
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/+/122215 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--sw/inc/swregion.hxx20
-rw-r--r--sw/source/core/bastyp/swregion.cxx15
-rw-r--r--sw/source/core/crsr/viscrs.cxx6
-rw-r--r--sw/source/core/view/viewimp.cxx5
-rw-r--r--sw/source/core/view/viewsh.cxx7
5 files changed, 38 insertions, 15 deletions
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 19ab3c3c988d..a2e3c405707d 100644
--- a/sw/source/core/bastyp/swregion.cxx
+++ b/sw/source/core/bastyp/swregion.cxx
@@ -28,6 +28,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,
@@ -46,8 +52,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>
@@ -140,6 +145,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 e8eab007038d..7d8064719228 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -836,9 +836,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 16657bb0849a..50304b384020 100644
--- a/sw/source/core/view/viewimp.cxx
+++ b/sw/source/core/view/viewimp.cxx
@@ -129,9 +129,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 0670e8e102b4..c78ea43516b1 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -329,9 +329,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;
@@ -1667,8 +1665,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() )