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 5a3c60f7c76fc0eca21f0fd468783e0ae48e3129 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:32:48 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/+/122215 Tested-by: Jenkins 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 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() )