[Libreoffice-commits] core.git: editeng/source include/tools sc/source sd/source svtools/source svx/source sw/source tools/source vcl/osx vcl/source vcl/win

Noel Grandin (via logerrit) logerrit at kemper.freedesktop.org
Fri Jun 7 09:02:23 UTC 2019


 editeng/source/editeng/impedit3.cxx                |    2 
 include/tools/gen.hxx                              |   83 ++++++++++++++-------
 sc/source/ui/view/gridwin.cxx                      |   55 +++++++------
 sd/source/filter/eppt/escherex.cxx                 |    3 
 svtools/source/control/tabbar.cxx                  |    6 -
 svx/source/sdr/contact/objectcontactofpageview.cxx |    3 
 sw/source/core/view/vdraw.cxx                      |    2 
 sw/source/uibase/uiview/viewport.cxx               |    8 +-
 tools/source/generic/gen.cxx                       |   32 ++++++--
 vcl/osx/salnativewidgets.cxx                       |    2 
 vcl/source/control/tabctrl.cxx                     |    2 
 vcl/source/gdi/mtfxmldump.cxx                      |    2 
 vcl/source/outdev/rect.cxx                         |    3 
 vcl/source/treelist/treelistbox.cxx                |    2 
 vcl/win/gdi/salnativewidgets-luna.cxx              |    3 
 15 files changed, 137 insertions(+), 71 deletions(-)

New commits:
commit a46a257794f1f53b294735fc876c394be23a3811
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Wed Jun 5 15:24:04 2019 +0200
Commit:     Noel Grandin <noel.grandin at collabora.co.uk>
CommitDate: Fri Jun 7 11:01:37 2019 +0200

    improve empty tools::Rectangle (width)
    
    This is the width part, the height part will come next.
    
    Instead of storing "empty" as a special value (which is easy to get
    wrong, eg. some image filters pass in that special value, expecting it
    to be a valid width), just use separate boolean values for width and
    height empty.
    
    Also lots of code was calling GetBottom() or GetRight() on an
    empty rectangle, getting back that magic value and doing calculations
    on it, resulting in completely bogus data.
    
    So
    (1) make the various Rectangle methods do something reasonable
        when the empty flags are set
    (2) fix various other code to handle empty better
    (3) assert when code accesses Bottom or Right and the empty flag
        is set.
    
    Change-Id: I1163378cd2773dd8b386210f83400bb6b4701069
    Reviewed-on: https://gerrit.libreoffice.org/73564
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
index ec3e10cf1290..bbcf17179fb4 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -2921,6 +2921,8 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, tools::Rectangle aClipRect, Po
 {
     if ( !GetUpdateMode() && !bStripOnly )
         return;
+    if ( aClipRect.IsEmpty() )
+        return;
 
     if ( !IsFormatted() )
         FormatDoc();
diff --git a/include/tools/gen.hxx b/include/tools/gen.hxx
index 0d9a81ebdcee..d84d359b543a 100644
--- a/include/tools/gen.hxx
+++ b/include/tools/gen.hxx
@@ -24,6 +24,7 @@
 #include <limits.h>
 #include <algorithm>
 #include <ostream>
+#include <cassert>
 
 class SvStream;
 namespace rtl
@@ -386,12 +387,12 @@ public:
                         Rectangle( const Point& rLT, const Size& rSize );
 
     long                Left() const    { return nLeft;   }
-    long                Right() const   { return nRight;  }
+    long                Right() const   { assert(!mbWidthEmpty); return nRight;  }
     long                Top() const     { return nTop;    }
     long                Bottom() const  { return nBottom; }
 
     void                SetLeft(long v)    { nLeft = v;   }
-    void                SetRight(long v)   { nRight = v;  }
+    void                SetRight(long v)   { nRight = v; mbWidthEmpty = false; }
     void                SetTop(long v)     { nTop = v;    }
     void                SetBottom(long v)  { nBottom = v; }
 
@@ -409,7 +410,17 @@ public:
     inline void         Move( long nHorzMoveDelta, long nVertMoveDelta );
     void                Move( Size const & s ) { Move(s.Width(), s.Height()); }
     long                AdjustLeft( long nHorzMoveDelta ) { nLeft += nHorzMoveDelta; return nLeft; }
-    long                AdjustRight( long nHorzMoveDelta ) { nRight += nHorzMoveDelta; return nRight; }
+    long                AdjustRight( long nHorzMoveDelta )
+    {
+        if (mbWidthEmpty)
+        {
+            mbWidthEmpty = false;
+            nRight = nLeft + nHorzMoveDelta - 1;
+        }
+        else
+            nRight += nHorzMoveDelta;
+        return nRight;
+    }
     long                AdjustTop( long nVertMoveDelta ) { nTop += nVertMoveDelta; return nTop; }
     long                AdjustBottom( long nVertMoveDelta ) { nBottom += nVertMoveDelta; return nBottom; }
     inline void         SetPos( const Point& rPoint );
@@ -432,11 +443,11 @@ public:
     bool                IsInside( const tools::Rectangle& rRect ) const;
     bool                IsOver( const tools::Rectangle& rRect ) const;
 
-    void                SetEmpty() { nRight = nBottom = RECT_EMPTY; }
-    void                SetWidthEmpty() { nRight = RECT_EMPTY; }
+    void                SetEmpty() { nRight = 0; nBottom = RECT_EMPTY; mbWidthEmpty = true; }
+    void                SetWidthEmpty() { nRight = 0; mbWidthEmpty = true; }
     void                SetHeightEmpty() { nBottom = RECT_EMPTY; }
     inline bool         IsEmpty() const;
-    bool                IsWidthEmpty() const { return nRight == RECT_EMPTY; }
+    bool                IsWidthEmpty() const { return mbWidthEmpty; }
     bool                IsHeightEmpty() const { return nBottom == RECT_EMPTY; }
 
     inline bool         operator == ( const tools::Rectangle& rRect ) const;
@@ -455,14 +466,19 @@ public:
     long                getX() const { return nLeft; }
     long                getY() const { return nTop; }
     /// Returns the difference between right and left, assuming the range includes one end, but not the other.
-    long                getWidth() const { return nRight - nLeft; }
+    long                getWidth() const { return mbWidthEmpty ? 0 : nRight - nLeft; }
     /// Returns the difference between bottom and top, assuming the range includes one end, but not the other.
     long                getHeight() const { return nBottom - nTop; }
     /// Set the left edge of the rectangle to x, preserving the width
-    void                setX( long x ) { nRight  += x - nLeft; nLeft = x; }
+    void                setX( long x )
+    {
+        if (!mbWidthEmpty)
+            nRight += x - nLeft;
+        nLeft = x;
+    }
     /// Set the top edge of the rectangle to y, preserving the height
     void                setY( long y ) { nBottom += y - nTop;  nTop  = y; }
-    void                setWidth( long n ) { nRight = nLeft + n; }
+    void                setWidth( long n ) { nRight = nLeft + n; mbWidthEmpty = false; }
     void                setHeight( long n ) { nBottom = nTop + n; }
     /// Returns the string representation of the rectangle, format is "x, y, width, height".
     rtl::OString        toString() const;
@@ -481,6 +497,7 @@ public:
     void                SaturatingSetY(long y);
 
 private:
+    bool                mbWidthEmpty : 1;
     long                nLeft;
     long                nTop;
     long                nRight;
@@ -491,7 +508,9 @@ private:
 inline tools::Rectangle::Rectangle()
 {
     nLeft = nTop = 0;
-    nRight = nBottom = RECT_EMPTY;
+    nRight = 0;
+    nBottom = RECT_EMPTY;
+    mbWidthEmpty = true;
 }
 
 inline tools::Rectangle::Rectangle( const Point& rLT, const Point& rRB )
@@ -500,6 +519,7 @@ inline tools::Rectangle::Rectangle( const Point& rLT, const Point& rRB )
     nTop    = rLT.Y();
     nRight  = rRB.X();
     nBottom = rRB.Y();
+    mbWidthEmpty = false;
 }
 
 inline tools::Rectangle::Rectangle( long _nLeft,  long _nTop,
@@ -509,26 +529,30 @@ inline tools::Rectangle::Rectangle( long _nLeft,  long _nTop,
     nTop    = _nTop;
     nRight  = _nRight;
     nBottom = _nBottom;
+    mbWidthEmpty = false;
 }
 
 inline tools::Rectangle::Rectangle( long _nLeft,  long _nTop )
 {
     nLeft   = _nLeft;
     nTop    = _nTop;
-    nRight = nBottom = RECT_EMPTY;
+    nRight  =  0;
+    nBottom = RECT_EMPTY;
+    mbWidthEmpty = true;
 }
 
 inline tools::Rectangle::Rectangle( const Point& rLT, const Size& rSize )
 {
     nLeft   = rLT.X();
     nTop    = rLT.Y();
-    nRight  = rSize.Width()  ? nLeft+(rSize.Width()-1) : RECT_EMPTY;
+    nRight  = rSize.Width()  ? nLeft+(rSize.Width()-1) : 0;
     nBottom = rSize.Height() ? nTop+(rSize.Height()-1) : RECT_EMPTY;
+    mbWidthEmpty  = rSize.Width() == 0;
 }
 
 inline bool tools::Rectangle::IsEmpty() const
 {
-    return (nRight == RECT_EMPTY) || (nBottom == RECT_EMPTY);
+    return mbWidthEmpty || (nBottom == RECT_EMPTY);
 }
 
 inline Point tools::Rectangle::TopLeft() const
@@ -538,7 +562,7 @@ inline Point tools::Rectangle::TopLeft() const
 
 inline Point tools::Rectangle::TopRight() const
 {
-    return Point( (nRight == RECT_EMPTY) ? nLeft : nRight, nTop );
+    return Point( mbWidthEmpty ? nLeft : nRight, nTop );
 }
 
 inline Point tools::Rectangle::BottomLeft() const
@@ -548,7 +572,7 @@ inline Point tools::Rectangle::BottomLeft() const
 
 inline Point tools::Rectangle::BottomRight() const
 {
-    return Point( (nRight  == RECT_EMPTY) ? nLeft : nRight,
+    return Point( mbWidthEmpty ? nLeft : nRight,
                   (nBottom == RECT_EMPTY) ? nTop  : nBottom );
 }
 
@@ -598,7 +622,7 @@ inline void tools::Rectangle::Move( long nHorzMove, long nVertMove )
 {
     nLeft += nHorzMove;
     nTop  += nVertMove;
-    if ( nRight != RECT_EMPTY )
+    if ( !mbWidthEmpty )
         nRight += nHorzMove;
     if ( nBottom != RECT_EMPTY )
         nBottom += nVertMove;
@@ -606,7 +630,7 @@ inline void tools::Rectangle::Move( long nHorzMove, long nVertMove )
 
 inline void tools::Rectangle::SetPos( const Point& rPoint )
 {
-    if ( nRight != RECT_EMPTY )
+    if ( !mbWidthEmpty )
         nRight += rPoint.X() - nLeft;
     if ( nBottom != RECT_EMPTY )
         nBottom += rPoint.Y() - nTop;
@@ -617,7 +641,7 @@ inline void tools::Rectangle::SetPos( const Point& rPoint )
 inline long tools::Rectangle::GetWidth() const
 {
     long n;
-    if ( nRight == RECT_EMPTY )
+    if ( mbWidthEmpty )
         n = 0;
     else
     {
@@ -670,22 +694,20 @@ inline bool tools::Rectangle::operator == ( const tools::Rectangle& rRect ) cons
     return (nLeft   == rRect.nLeft   ) &&
            (nTop    == rRect.nTop    ) &&
            (nRight  == rRect.nRight  ) &&
-           (nBottom == rRect.nBottom );
+           (nBottom == rRect.nBottom ) &&
+           (mbWidthEmpty == rRect.mbWidthEmpty);
 }
 
 inline bool tools::Rectangle::operator != ( const tools::Rectangle& rRect ) const
 {
-    return (nLeft   != rRect.nLeft   ) ||
-           (nTop    != rRect.nTop    ) ||
-           (nRight  != rRect.nRight  ) ||
-           (nBottom != rRect.nBottom );
+    return !(operator==(rRect));
 }
 
 inline tools::Rectangle& tools::Rectangle::operator +=( const Point& rPt )
 {
     nLeft += rPt.X();
     nTop  += rPt.Y();
-    if ( nRight != RECT_EMPTY )
+    if ( !mbWidthEmpty )
         nRight += rPt.X();
     if ( nBottom != RECT_EMPTY )
         nBottom += rPt.Y();
@@ -696,7 +718,7 @@ inline tools::Rectangle& tools::Rectangle::operator -= ( const Point& rPt )
 {
     nLeft -= rPt.X();
     nTop  -= rPt.Y();
-    if ( nRight != RECT_EMPTY )
+    if ( !mbWidthEmpty )
         nRight -= rPt.X();
     if ( nBottom != RECT_EMPTY )
         nBottom -= rPt.Y();
@@ -726,7 +748,13 @@ inline void tools::Rectangle::expand(long nExpandBy)
 {
     nLeft   -= nExpandBy;
     nTop    -= nExpandBy;
-    nRight  += nExpandBy;
+    if (mbWidthEmpty)
+    {
+        nRight  = nLeft + nExpandBy - 1;
+        mbWidthEmpty = false;
+    }
+    else
+        nRight  += nExpandBy;
     nBottom += nExpandBy;
 }
 
@@ -734,7 +762,8 @@ inline void tools::Rectangle::shrink(long nShrinkBy)
 {
     nLeft   += nShrinkBy;
     nTop    += nShrinkBy;
-    nRight  -= nShrinkBy;
+    if (!mbWidthEmpty)
+        nRight  -= nShrinkBy;
     nBottom -= nShrinkBy;
 }
 
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index e043cfc4d857..0b17e43f42b9 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -6001,40 +6001,43 @@ void ScGridWindow::UpdateCursorOverlay()
             long nSizeYPix;
             pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
 
-            if (bLayoutRTL)
-                aScrPos.AdjustX( -(nSizeXPix - 2) );       // move instead of mirroring
+            if (nSizeXPix>1 && nSizeYPix>1)
+            {
+                if (bLayoutRTL)
+                    aScrPos.AdjustX( -(nSizeXPix - 2) );       // move instead of mirroring
 
-            // show the cursor as 4 (thin) rectangles
-            tools::Rectangle aRect(aScrPos, Size(nSizeXPix - 1, nSizeYPix - 1));
+                // show the cursor as 4 (thin) rectangles
+                tools::Rectangle aRect(aScrPos, Size(nSizeXPix - 1, nSizeYPix - 1));
 
-            float fScaleFactor = GetDPIScaleFactor();
+                float fScaleFactor = GetDPIScaleFactor();
 
-            long aCursorWidth = 1 * fScaleFactor;
+                long aCursorWidth = 1 * fScaleFactor;
 
-            tools::Rectangle aLeft = aRect;
-            aLeft.AdjustTop( -aCursorWidth );
-            aLeft.AdjustBottom(aCursorWidth );
-            aLeft.SetRight( aLeft.Left() );
-            aLeft.AdjustLeft( -aCursorWidth );
+                tools::Rectangle aLeft = aRect;
+                aLeft.AdjustTop( -aCursorWidth );
+                aLeft.AdjustBottom(aCursorWidth );
+                aLeft.SetRight( aLeft.Left() );
+                aLeft.AdjustLeft( -aCursorWidth );
 
-            tools::Rectangle aRight = aRect;
-            aRight.AdjustTop( -aCursorWidth );
-            aRight.AdjustBottom(aCursorWidth );
-            aRight.SetLeft( aRight.Right() );
-            aRight.AdjustRight(aCursorWidth );
+                tools::Rectangle aRight = aRect;
+                aRight.AdjustTop( -aCursorWidth );
+                aRight.AdjustBottom(aCursorWidth );
+                aRight.SetLeft( aRight.Right() );
+                aRight.AdjustRight(aCursorWidth );
 
-            tools::Rectangle aTop = aRect;
-            aTop.SetBottom( aTop.Top() );
-            aTop.AdjustTop( -aCursorWidth );
+                tools::Rectangle aTop = aRect;
+                aTop.SetBottom( aTop.Top() );
+                aTop.AdjustTop( -aCursorWidth );
 
-            tools::Rectangle aBottom = aRect;
-            aBottom.SetTop( aBottom.Bottom() );
-            aBottom.AdjustBottom(aCursorWidth );
+                tools::Rectangle aBottom = aRect;
+                aBottom.SetTop( aBottom.Bottom() );
+                aBottom.AdjustBottom(aCursorWidth );
 
-            aPixelRects.push_back(aLeft);
-            aPixelRects.push_back(aRight);
-            aPixelRects.push_back(aTop);
-            aPixelRects.push_back(aBottom);
+                aPixelRects.push_back(aLeft);
+                aPixelRects.push_back(aRight);
+                aPixelRects.push_back(aTop);
+                aPixelRects.push_back(aBottom);
+            }
         }
     }
 
diff --git a/sd/source/filter/eppt/escherex.cxx b/sd/source/filter/eppt/escherex.cxx
index 5032c27210b6..4b2adb3ee3bd 100644
--- a/sd/source/filter/eppt/escherex.cxx
+++ b/sd/source/filter/eppt/escherex.cxx
@@ -220,9 +220,10 @@ sal_uInt32 PptEscherEx::EnterGroup( ::tools::Rectangle const * pBoundRect, SvMem
         OpenContainer( ESCHER_SpContainer );
         AddAtom( 16, ESCHER_Spgr, 1 );
         PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel, mpOutStrm->Tell() );
+        // FIXME what to do with empty rectangles?
         mpOutStrm ->WriteInt32( aRect.Left() )  // bounding box for the grouped shapes to which they are attached
                    .WriteInt32( aRect.Top() )
-                   .WriteInt32( aRect.Right() )
+                   .WriteInt32( aRect.IsWidthEmpty() ? -32767 : aRect.Right() )
                    .WriteInt32( aRect.Bottom() );
 
         nShapeId = GenerateShapeId();
diff --git a/svtools/source/control/tabbar.cxx b/svtools/source/control/tabbar.cxx
index 8ee61e42cb61..a14b16300b8b 100644
--- a/svtools/source/control/tabbar.cxx
+++ b/svtools/source/control/tabbar.cxx
@@ -864,7 +864,7 @@ void TabBar::ImplShowPage( sal_uInt16 nPos )
     auto& pItem = mpImpl->mpItemList[nPos];
     if (nPos < mnFirstPos)
         SetFirstPageId( pItem->mnId );
-    else if (pItem->maRect.Right() > nWidth)
+    else if (!pItem->maRect.IsEmpty() && pItem->maRect.Right() > nWidth)
     {
         while (pItem->maRect.Right() > nWidth)
         {
@@ -1868,8 +1868,8 @@ void TabBar::SetCurPageId(sal_uInt16 nPageId)
             if (pItem->maRect.IsEmpty())
                 ImplFormat();
 
-            while ((mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) ||
-                    pItem->maRect.IsEmpty())
+            while (pItem->maRect.IsEmpty() ||
+                   (mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)))
             {
                 sal_uInt16 nNewPos = mnFirstPos + 1;
                 // assure at least the actual tabpages are visible as first tabpage
diff --git a/svx/source/sdr/contact/objectcontactofpageview.cxx b/svx/source/sdr/contact/objectcontactofpageview.cxx
index 3bda11b111f6..4961d4610c34 100644
--- a/svx/source/sdr/contact/objectcontactofpageview.cxx
+++ b/svx/source/sdr/contact/objectcontactofpageview.cxx
@@ -213,6 +213,9 @@ namespace sdr
                 aViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
             }
 
+            if (aViewRange.isEmpty())
+                return;
+
             // update local ViewInformation2D
             const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
                 basegfx::B2DHomMatrix(),
diff --git a/sw/source/core/view/vdraw.cxx b/sw/source/core/view/vdraw.cxx
index 6c844c74a634..abaf3f8e28fe 100644
--- a/sw/source/core/view/vdraw.cxx
+++ b/sw/source/core/view/vdraw.cxx
@@ -204,7 +204,7 @@ void SwViewShellImp::NotifySizeChg( const Size &rNewSz )
     bool bCheckDrawObjs = false;
     if ( aDocRect != rOldWork )
     {
-        if ( rOldWork.Bottom() > aDocRect.Bottom() || rOldWork.Right() > aDocRect.Right())
+        if ( !rOldWork.IsEmpty() && (rOldWork.Bottom() > aDocRect.Bottom() || rOldWork.Right() > aDocRect.Right()))
             bCheckDrawObjs = true;
         GetDrawView()->SetWorkArea( aDocRect );
     }
diff --git a/sw/source/uibase/uiview/viewport.cxx b/sw/source/uibase/uiview/viewport.cxx
index 2fa7e12f5afe..bebcaa1317a2 100644
--- a/sw/source/uibase/uiview/viewport.cxx
+++ b/sw/source/uibase/uiview/viewport.cxx
@@ -316,9 +316,11 @@ void SwView::SetVisArea( const Point &rPt, bool bUpdateScrollbar )
 
     const long lXDiff = m_aVisArea.Left() - aPt.X();
     const long lYDiff = m_aVisArea.Top()  - aPt.Y();
-    SetVisArea( tools::Rectangle( aPt,
-            Point( m_aVisArea.Right() - lXDiff, m_aVisArea.Bottom() - lYDiff ) ),
-            bUpdateScrollbar);
+    tools::Rectangle aNewVisArea(m_aVisArea);
+    aNewVisArea.SetPos(aPt);
+    aNewVisArea.AdjustRight(-lXDiff);
+    aNewVisArea.AdjustBottom(-lYDiff);
+    SetVisArea( aNewVisArea, bUpdateScrollbar);
 }
 
 void SwView::CheckVisArea()
diff --git a/tools/source/generic/gen.cxx b/tools/source/generic/gen.cxx
index 3593801579ac..6438405c99e2 100644
--- a/tools/source/generic/gen.cxx
+++ b/tools/source/generic/gen.cxx
@@ -55,11 +55,20 @@ OString Pair::toString() const
 void tools::Rectangle::SetSize( const Size& rSize )
 {
     if ( rSize.Width() < 0 )
+    {
         nRight  = nLeft + rSize.Width() +1;
+        mbWidthEmpty = false;
+    }
     else if ( rSize.Width() > 0 )
+    {
         nRight  = nLeft + rSize.Width() -1;
+        mbWidthEmpty = false;
+    }
     else
-        nRight = RECT_EMPTY;
+    {
+        nRight = 0;
+        mbWidthEmpty = true;
+    }
 
     if ( rSize.Height() < 0 )
         nBottom  = nTop + rSize.Height() +1;
@@ -72,11 +81,20 @@ void tools::Rectangle::SetSize( const Size& rSize )
 void tools::Rectangle::SaturatingSetSize(const Size& rSize)
 {
     if (rSize.Width() < 0)
+    {
         nRight = o3tl::saturating_add(nLeft, (rSize.Width() + 1));
+        mbWidthEmpty = false;
+    }
     else if ( rSize.Width() > 0 )
+    {
         nRight = o3tl::saturating_add(nLeft, (rSize.Width() - 1));
+        mbWidthEmpty = false;
+    }
     else
-        nRight = RECT_EMPTY;
+    {
+        nRight = 0;
+        mbWidthEmpty = true;
+    }
 
     if ( rSize.Height() < 0 )
         nBottom = o3tl::saturating_add(nTop, (rSize.Height() + 1));
@@ -88,7 +106,8 @@ void tools::Rectangle::SaturatingSetSize(const Size& rSize)
 
 void tools::Rectangle::SaturatingSetX(long x)
 {
-    nRight = o3tl::saturating_add(nRight, x - nLeft);
+    if (!mbWidthEmpty)
+        nRight = o3tl::saturating_add(nRight, x - nLeft);
     nLeft = x;
 }
 
@@ -146,7 +165,7 @@ tools::Rectangle& tools::Rectangle::Intersection( const tools::Rectangle& rRect
 
 void tools::Rectangle::Justify()
 {
-    if ( (nRight < nLeft) && (nRight != RECT_EMPTY) )
+    if ( (nRight < nLeft) && !mbWidthEmpty )
     {
         std::swap(nLeft, nRight);
     }
@@ -206,8 +225,9 @@ SvStream& ReadRectangle( SvStream& rIStream, tools::Rectangle& rRect )
 
     rRect.nLeft = nTmpL;
     rRect.nTop = nTmpT;
-    rRect.nRight = nTmpR;
+    rRect.nRight = nTmpR == Rectangle::RECT_EMPTY ? 0 : nTmpR;
     rRect.nBottom = nTmpB;
+    rRect.mbWidthEmpty = nTmpR == Rectangle::RECT_EMPTY;
 
     return rIStream;
 }
@@ -216,7 +236,7 @@ SvStream& WriteRectangle( SvStream& rOStream, const tools::Rectangle& rRect )
 {
     rOStream.WriteInt32( rRect.nLeft )
             .WriteInt32( rRect.nTop )
-            .WriteInt32( rRect.nRight )
+            .WriteInt32( rRect.mbWidthEmpty ? Rectangle::RECT_EMPTY : rRect.nRight )
             .WriteInt32( rRect.nBottom );
 
     return rOStream;
diff --git a/vcl/osx/salnativewidgets.cxx b/vcl/osx/salnativewidgets.cxx
index ad1362d438de..481d7a90e5fe 100644
--- a/vcl/osx/salnativewidgets.cxx
+++ b/vcl/osx/salnativewidgets.cxx
@@ -1017,6 +1017,8 @@ bool AquaSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPa
                                                 tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion )
 
 {
+    if (rControlRegion.IsEmpty()) // nothing to do
+        return false;
     bool toReturn = false;
 
     tools::Rectangle aCtrlBoundRect( rControlRegion );
diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx
index d5b9eeeeacfa..eeede1ae1e1c 100644
--- a/vcl/source/control/tabctrl.cxx
+++ b/vcl/source/control/tabctrl.cxx
@@ -2123,7 +2123,7 @@ Size TabControl::calculateRequisition() const
         tools::Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aOptimalPageSize.Width(), LONG_MAX);
         if (aTabRect.Bottom() > nTabLabelsBottom)
             nTabLabelsBottom = aTabRect.Bottom();
-        if (aTabRect.Right() > nTabLabelsRight)
+        if (!aTabRect.IsEmpty() && aTabRect.Right() > nTabLabelsRight)
             nTabLabelsRight = aTabRect.Right();
     }
 
diff --git a/vcl/source/gdi/mtfxmldump.cxx b/vcl/source/gdi/mtfxmldump.cxx
index 8c168a89d4c4..3f681a08a674 100644
--- a/vcl/source/gdi/mtfxmldump.cxx
+++ b/vcl/source/gdi/mtfxmldump.cxx
@@ -459,7 +459,7 @@ void writeRectangle(tools::XmlWriter& rWriter, tools::Rectangle const& rRectangl
 {
     rWriter.attribute("left", rRectangle.Left());
     rWriter.attribute("top", rRectangle.Top());
-    rWriter.attribute("right", rRectangle.Right());
+    rWriter.attribute("right", rRectangle.IsWidthEmpty() ? -32767 : rRectangle.Right());
     rWriter.attribute("bottom", rRectangle.Bottom());
 }
 
diff --git a/vcl/source/outdev/rect.cxx b/vcl/source/outdev/rect.cxx
index 67343278a1be..14d341ac6b8f 100644
--- a/vcl/source/outdev/rect.cxx
+++ b/vcl/source/outdev/rect.cxx
@@ -376,7 +376,8 @@ BmpMirrorFlags AdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
 
 void AdjustTwoRect( SalTwoRect& rTwoRect, const tools::Rectangle& rValidSrcRect )
 {
-    if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) ||
+    long right = rValidSrcRect.IsEmpty() ? rValidSrcRect.Left() : rValidSrcRect.Right();
+    if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= right ) ||
         ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) ||
         ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) ||
         ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() ) )
diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx
index f42aac4983af..b91fb5552d61 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -2770,7 +2770,7 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, long nLine, vcl::Render
             {
                 rRenderContext.SetFillColor(aBackgroundColor);
                 // this case may occur for smaller horizontal resizes
-                if (aRect.Left() < aRect.Right())
+                if (!aRect.IsEmpty() && (aRect.Left() < aRect.Right()))
                     rRenderContext.DrawRect(aRect);
             }
         }
diff --git a/vcl/win/gdi/salnativewidgets-luna.cxx b/vcl/win/gdi/salnativewidgets-luna.cxx
index 422a86c27045..1b49bfba61ad 100644
--- a/vcl/win/gdi/salnativewidgets-luna.cxx
+++ b/vcl/win/gdi/salnativewidgets-luna.cxx
@@ -1155,6 +1155,9 @@ bool WinSalGraphics::drawNativeControl( ControlType nType,
     bool bOk = false;
     HTHEME hTheme = nullptr;
 
+    if (rControlRegion.IsEmpty()) // nothing to do
+           return true;
+
     tools::Rectangle buttonRect = rControlRegion;
     tools::Rectangle cacheRect = rControlRegion;
     Size keySize = cacheRect.GetSize();


More information about the Libreoffice-commits mailing list