From 55a18fcee6ba152e9db154cc925d2f578f31a9ae Mon Sep 17 00:00:00 2001 From: "Armin Le Grand (Allotropia)" Date: Mon, 19 Apr 2021 19:51:27 +0200 Subject: tdf#141761 Avoid vanishing FormControls For details see task documentaion, but BG is that a Rectangle gets not transformed in OutputDevice::LogicToPixel and corresponding methods of OutputDevice due to the given Rectangle.IsEmpty() == true. This ignores that the Rectangle has a valid position and that we have cases where a Rectangle is used to hold a Position without having a Size != 0 in X and Y. Thus I added transforming the Position in these methods in all cases - a Rectangle always has a valid position - and take care of Sizes that exist. This *may* need to be done different due to old hiccups of Rectangle itself, see explanation at OutputDevice::ImplLogicToDevicePixel Had to do it different now, see comment in map.cxx for expalantions. Also needed to adapt the ancient optical geometric paint position correctionsfor Buttons - these can get zero or negative due to using Zoom and MapMode settings. A Width shoul not get zero or negative. Adapted to LibreOffice-7-1 as needed. Change-Id: Ide085fbe74f9c0387de3c1bf6320b7e873238029 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114304 Tested-by: Jenkins Reviewed-by: Armin Le Grand (cherry picked from commit 35e4a45260f128f353d25e2a2f2b800e6bd11d61) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114596 --- vcl/source/control/button.cxx | 22 ++++- vcl/source/outdev/map.cxx | 217 +++++++++++++++++++++++++++--------------- 2 files changed, 160 insertions(+), 79 deletions(-) diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx index 91a4aa4543a3..d0614c4ab96c 100644 --- a/vcl/source/control/button.cxx +++ b/vcl/source/control/button.cxx @@ -825,7 +825,11 @@ void PushButton::ImplDrawPushButtonContent(OutputDevice *pDev, DrawFlags nDrawFl nSymbolSize = aSize.Width() / 2; nSeparatorX = aInRect.Right() - 2*nSymbolSize; - aSize.AdjustWidth( -(2*nSymbolSize) ); + + // tdf#141761 Minimum width should be (1) Pixel, see comment + // with same task number above for more info + const tools::Long nWidthAdjust(2*nSymbolSize); + aSize.setWidth(std::max(static_cast(1), aSize.getWidth() - nWidthAdjust)); // center symbol rectangle in the separated area aSymbolRect.AdjustRight( -(nSymbolSize/2) ); @@ -1982,7 +1986,16 @@ void RadioButton::ImplDraw( OutputDevice* pDev, DrawFlags nDrawFlags, Size aSize( rSize ); Point aPos( rPos ); aPos.AdjustX(rImageSize.Width() + nImageSep ); - aSize.AdjustWidth( -(rImageSize.Width() + nImageSep) ); + + // tdf#141761 Old (convenience?) adjustment of width may lead to empty + // or negative(!) Size, that needs to be avoided. The coordinate context + // is pixel-oriented (all Paints of Controls are, historically), so + // the minimum width should be '1' Pixel. + // Hint: nImageSep is based on Zoom (using Window::CalcZoom) and + // MapModes (using Window::GetDrawPixel) - so potenially a wide range + // of unpredictable values is possible + const tools::Long nWidthAdjust(rImageSize.Width() + nImageSep); + aSize.setWidth(std::max(static_cast(1), aSize.getWidth() - nWidthAdjust)); // if the text rect height is smaller than the height of the image // then for single lines the default should be centered text @@ -2996,7 +3009,10 @@ void CheckBox::ImplDraw( OutputDevice* pDev, DrawFlags nDrawFlags, Size aSize( rSize ); Point aPos( rPos ); aPos.AdjustX(rImageSize.Width() + nImageSep ); - aSize.AdjustWidth( -(rImageSize.Width() + nImageSep) ); + + // tdf#141761 See comment with same ID above + const tools::Long nWidthAdjust(rImageSize.Width() + nImageSep); + aSize.setWidth(std::max(static_cast(1), aSize.getWidth() - nWidthAdjust)); // if the text rect height is smaller than the height of the image // then for single lines the default should be centered text diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index efd8e587ce0e..3f478f2fdf88 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -405,23 +405,48 @@ Size OutputDevice::ImplLogicToDevicePixel( const Size& rLogicSize ) const tools::Rectangle OutputDevice::ImplLogicToDevicePixel( const tools::Rectangle& rLogicRect ) const { - if ( rLogicRect.IsEmpty() ) - return rLogicRect; + // tdf#141761 IsEmpty() removed + // Even if rLogicRect.IsEmpty(), transform of the Position contained + // in the Rectangle is necessary. Due to Rectangle::Right() returning + // Left() when IsEmpty(), the code *could* stay unchanged (same for Bottom), + // but: + // The Rectangle constructor used with the four tools::Long values does not + // check for IsEmpty(), so to keep that state correct there are two possibilities: + // (1) Add a test to the Rectangle constructor in question + // (2) Do it handish here + // I have tried (1) first, but test Test::test_rectangle() claims that for + // tools::Rectangle aRect(1, 1, 1, 1); + // tools::Long(1) == aRect.GetWidth() + // tools::Long(0) == aRect.getWidth() + // (remember: this means Left == Right == 1 -> GetWidth => 1, getWidth == 0) + // so indeed tthe 1's have to go uncommened/unchecked into the data body + // of rectangle. Switching to (2) *is* needed, doing so + tools::Rectangle aRetval; if ( !mbMap ) { - return tools::Rectangle( rLogicRect.Left()+mnOutOffX, rLogicRect.Top()+mnOutOffY, - rLogicRect.Right()+mnOutOffX, rLogicRect.Bottom()+mnOutOffY ); + aRetval = tools::Rectangle( + rLogicRect.Left()+mnOutOffX, + rLogicRect.Top()+mnOutOffY, + rLogicRect.IsWidthEmpty() ? 0 : rLogicRect.Right()+mnOutOffX, + rLogicRect.IsHeightEmpty() ? 0 : rLogicRect.Bottom()+mnOutOffY ); + } + else + { + aRetval = tools::Rectangle( + ImplLogicToPixel( rLogicRect.Left()+maMapRes.mnMapOfsX, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffX+mnOutOffOrigX, + ImplLogicToPixel( rLogicRect.Top()+maMapRes.mnMapOfsY, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffY+mnOutOffOrigY, + rLogicRect.IsWidthEmpty() ? 0 : ImplLogicToPixel( rLogicRect.Right()+maMapRes.mnMapOfsX, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffX+mnOutOffOrigX, + rLogicRect.IsHeightEmpty() ? 0 : ImplLogicToPixel( rLogicRect.Bottom()+maMapRes.mnMapOfsY, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffY+mnOutOffOrigY ); } - return tools::Rectangle( ImplLogicToPixel( rLogicRect.Left()+maMapRes.mnMapOfsX, mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffX+mnOutOffOrigX, - ImplLogicToPixel( rLogicRect.Top()+maMapRes.mnMapOfsY, mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffY+mnOutOffOrigY, - ImplLogicToPixel( rLogicRect.Right()+maMapRes.mnMapOfsX, mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffX+mnOutOffOrigX, - ImplLogicToPixel( rLogicRect.Bottom()+maMapRes.mnMapOfsY, mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffY+mnOutOffOrigY ); + if(rLogicRect.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rLogicRect.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } tools::Polygon OutputDevice::ImplLogicToDevicePixel( const tools::Polygon& rLogicPoly ) const @@ -506,23 +531,33 @@ LineInfo OutputDevice::ImplLogicToDevicePixel( const LineInfo& rLineInfo ) const tools::Rectangle OutputDevice::ImplDevicePixelToLogic( const tools::Rectangle& rPixelRect ) const { - if ( rPixelRect.IsEmpty() ) - return rPixelRect; + // tdf#141761 see comments above, IsEmpty() removed + tools::Rectangle aRetval; if ( !mbMap ) { - return tools::Rectangle( rPixelRect.Left()-mnOutOffX, rPixelRect.Top()-mnOutOffY, - rPixelRect.Right()-mnOutOffX, rPixelRect.Bottom()-mnOutOffY ); + aRetval = tools::Rectangle( + rPixelRect.Left()-mnOutOffX, + rPixelRect.Top()-mnOutOffY, + rPixelRect.IsWidthEmpty() ? 0 : rPixelRect.Right()-mnOutOffX, + rPixelRect.IsHeightEmpty() ? 0 : rPixelRect.Bottom()-mnOutOffY ); + } + else + { + aRetval = tools::Rectangle( + ImplPixelToLogic( rPixelRect.Left()-mnOutOffX-mnOutOffOrigX, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )-maMapRes.mnMapOfsX, + ImplPixelToLogic( rPixelRect.Top()-mnOutOffY-mnOutOffOrigY, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )-maMapRes.mnMapOfsY, + rPixelRect.IsWidthEmpty() ? 0 : ImplPixelToLogic( rPixelRect.Right()-mnOutOffX-mnOutOffOrigX, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )-maMapRes.mnMapOfsX, + rPixelRect.IsHeightEmpty() ? 0 : ImplPixelToLogic( rPixelRect.Bottom()-mnOutOffY-mnOutOffOrigY, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )-maMapRes.mnMapOfsY ); } - return tools::Rectangle( ImplPixelToLogic( rPixelRect.Left()-mnOutOffX-mnOutOffOrigX, mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )-maMapRes.mnMapOfsX, - ImplPixelToLogic( rPixelRect.Top()-mnOutOffY-mnOutOffOrigY, mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )-maMapRes.mnMapOfsY, - ImplPixelToLogic( rPixelRect.Right()-mnOutOffX-mnOutOffOrigX, mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )-maMapRes.mnMapOfsX, - ImplPixelToLogic( rPixelRect.Bottom()-mnOutOffY-mnOutOffOrigY, mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )-maMapRes.mnMapOfsY ); + if(rPixelRect.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rPixelRect.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } vcl::Region OutputDevice::ImplPixelToDevicePixel( const vcl::Region& rRegion ) const @@ -851,18 +886,23 @@ Size OutputDevice::LogicToPixel( const Size& rLogicSize ) const tools::Rectangle OutputDevice::LogicToPixel( const tools::Rectangle& rLogicRect ) const { - - if ( !mbMap || rLogicRect.IsEmpty() ) + // tdf#141761 see comments above, IsEmpty() removed + if ( !mbMap ) return rLogicRect; - return tools::Rectangle( ImplLogicToPixel( rLogicRect.Left() + maMapRes.mnMapOfsX, mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffOrigX, - ImplLogicToPixel( rLogicRect.Top() + maMapRes.mnMapOfsY, mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffOrigY, - ImplLogicToPixel( rLogicRect.Right() + maMapRes.mnMapOfsX, mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffOrigX, - ImplLogicToPixel( rLogicRect.Bottom() + maMapRes.mnMapOfsY, mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffOrigY ); + tools::Rectangle aRetval( + ImplLogicToPixel( rLogicRect.Left() + maMapRes.mnMapOfsX, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffOrigX, + ImplLogicToPixel( rLogicRect.Top() + maMapRes.mnMapOfsY, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffOrigY, + rLogicRect.IsWidthEmpty() ? 0 : ImplLogicToPixel( rLogicRect.Right() + maMapRes.mnMapOfsX, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX )+mnOutOffOrigX, + rLogicRect.IsHeightEmpty() ? 0 : ImplLogicToPixel( rLogicRect.Bottom() + maMapRes.mnMapOfsY, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY )+mnOutOffOrigY ); + + if(rLogicRect.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rLogicRect.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } tools::Polygon OutputDevice::LogicToPixel( const tools::Polygon& rLogicPoly ) const @@ -987,22 +1027,27 @@ Size OutputDevice::LogicToPixel( const Size& rLogicSize, tools::Rectangle OutputDevice::LogicToPixel( const tools::Rectangle& rLogicRect, const MapMode& rMapMode ) const { - - if ( rMapMode.IsDefault() || rLogicRect.IsEmpty() ) + // tdf#141761 see comments above, IsEmpty() removed + if ( rMapMode.IsDefault() ) return rLogicRect; // convert MapMode resolution and convert ImplMapRes aMapRes; ImplCalcMapResolution(rMapMode, mnDPIX, mnDPIY, aMapRes); - return tools::Rectangle( ImplLogicToPixel( rLogicRect.Left() + aMapRes.mnMapOfsX, mnDPIX, - aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX )+mnOutOffOrigX, - ImplLogicToPixel( rLogicRect.Top() + aMapRes.mnMapOfsY, mnDPIY, - aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY )+mnOutOffOrigY, - ImplLogicToPixel( rLogicRect.Right() + aMapRes.mnMapOfsX, mnDPIX, - aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX )+mnOutOffOrigX, - ImplLogicToPixel( rLogicRect.Bottom() + aMapRes.mnMapOfsY, mnDPIY, - aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY )+mnOutOffOrigY ); + tools::Rectangle aRetval( + ImplLogicToPixel( rLogicRect.Left() + aMapRes.mnMapOfsX, mnDPIX, aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX )+mnOutOffOrigX, + ImplLogicToPixel( rLogicRect.Top() + aMapRes.mnMapOfsY, mnDPIY, aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY )+mnOutOffOrigY, + rLogicRect.IsWidthEmpty() ? 0 : ImplLogicToPixel( rLogicRect.Right() + aMapRes.mnMapOfsX, mnDPIX, aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX )+mnOutOffOrigX, + rLogicRect.IsHeightEmpty() ? 0 : ImplLogicToPixel( rLogicRect.Bottom() + aMapRes.mnMapOfsY, mnDPIY, aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY )+mnOutOffOrigY ); + + if(rLogicRect.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rLogicRect.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } tools::Polygon OutputDevice::LogicToPixel( const tools::Polygon& rLogicPoly, @@ -1072,18 +1117,23 @@ Size OutputDevice::PixelToLogic( const Size& rDeviceSize ) const tools::Rectangle OutputDevice::PixelToLogic( const tools::Rectangle& rDeviceRect ) const { - - if ( !mbMap || rDeviceRect.IsEmpty() ) + // tdf#141761 see comments above, IsEmpty() removed + if ( !mbMap ) return rDeviceRect; - return tools::Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX ) - maMapRes.mnMapOfsX - mnOutOffLogicX, - ImplPixelToLogic( rDeviceRect.Top(), mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY ) - maMapRes.mnMapOfsY - mnOutOffLogicY, - ImplPixelToLogic( rDeviceRect.Right(), mnDPIX, - maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX ) - maMapRes.mnMapOfsX - mnOutOffLogicX, - ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY, - maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY ) - maMapRes.mnMapOfsY - mnOutOffLogicY ); + tools::Rectangle aRetval( + ImplPixelToLogic( rDeviceRect.Left(), mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX ) - maMapRes.mnMapOfsX - mnOutOffLogicX, + ImplPixelToLogic( rDeviceRect.Top(), mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY ) - maMapRes.mnMapOfsY - mnOutOffLogicY, + rDeviceRect.IsWidthEmpty() ? 0 : ImplPixelToLogic( rDeviceRect.Right(), mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX ) - maMapRes.mnMapOfsX - mnOutOffLogicX, + rDeviceRect.IsHeightEmpty() ? 0 : ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY ) - maMapRes.mnMapOfsY - mnOutOffLogicY ); + + if(rDeviceRect.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rDeviceRect.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } tools::Polygon OutputDevice::PixelToLogic( const tools::Polygon& rDevicePoly ) const @@ -1210,23 +1260,28 @@ Size OutputDevice::PixelToLogic( const Size& rDeviceSize, tools::Rectangle OutputDevice::PixelToLogic( const tools::Rectangle& rDeviceRect, const MapMode& rMapMode ) const { - // calculate nothing if default-MapMode - if ( rMapMode.IsDefault() || rDeviceRect.IsEmpty() ) + // tdf#141761 see comments above, IsEmpty() removed + if ( rMapMode.IsDefault() ) return rDeviceRect; // calculate MapMode-resolution and convert ImplMapRes aMapRes; ImplCalcMapResolution(rMapMode, mnDPIX, mnDPIY, aMapRes); - return tools::Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX, - aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX ) - aMapRes.mnMapOfsX - mnOutOffLogicX, - ImplPixelToLogic( rDeviceRect.Top(), mnDPIY, - aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY ) - aMapRes.mnMapOfsY - mnOutOffLogicY, - ImplPixelToLogic( rDeviceRect.Right(), mnDPIX, - aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX ) - aMapRes.mnMapOfsX - mnOutOffLogicX, - ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY, - aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY ) - aMapRes.mnMapOfsY - mnOutOffLogicY ); + tools::Rectangle aRetval( + ImplPixelToLogic( rDeviceRect.Left(), mnDPIX, aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX ) - aMapRes.mnMapOfsX - mnOutOffLogicX, + ImplPixelToLogic( rDeviceRect.Top(), mnDPIY, aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY ) - aMapRes.mnMapOfsY - mnOutOffLogicY, + rDeviceRect.IsWidthEmpty() ? 0 : ImplPixelToLogic( rDeviceRect.Right(), mnDPIX, aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX ) - aMapRes.mnMapOfsX - mnOutOffLogicX, + rDeviceRect.IsHeightEmpty() ? 0 : ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY, aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY ) - aMapRes.mnMapOfsY - mnOutOffLogicY ); + + if(rDeviceRect.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rDeviceRect.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } tools::Polygon OutputDevice::PixelToLogic( const tools::Polygon& rDevicePoly, @@ -1695,18 +1750,20 @@ tools::Rectangle OutputDevice::LogicToLogic( const tools::Rectangle& rRectSource MapUnit eUnitDest = rMapModeDest.GetMapUnit(); verifyUnitSourceDest( eUnitSource, eUnitDest ); + tools::Rectangle aRetval; + if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple()) { ENTER3( eUnitSource, eUnitDest ); - auto left = fn3( rRectSource.Left(), nNumerator, nDenominator ); - auto top = fn3( rRectSource.Top(), nNumerator, nDenominator ); - if (rRectSource.IsEmpty()) - return tools::Rectangle( left, top ); + auto left = fn3(rRectSource.Left(), nNumerator, nDenominator); + auto top = fn3(rRectSource.Top(), nNumerator, nDenominator); + + // tdf#141761 see comments above, IsEmpty() removed + auto right = rRectSource.IsWidthEmpty() ? 0 : fn3(rRectSource.Right(), nNumerator, nDenominator); + auto bottom = rRectSource.IsHeightEmpty() ? 0 : fn3(rRectSource.Bottom(), nNumerator, nDenominator); - auto right = fn3( rRectSource.Right(), nNumerator, nDenominator ); - auto bottom = fn3( rRectSource.Bottom(), nNumerator, nDenominator ); - return tools::Rectangle(left, top, right, bottom); + aRetval = tools::Rectangle(left, top, right, bottom); } else { @@ -1720,19 +1777,27 @@ tools::Rectangle OutputDevice::LogicToLogic( const tools::Rectangle& rRectSource aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY, aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) - aMapResDest.mnMapOfsY; - if (rRectSource.IsEmpty()) - return tools::Rectangle(left, top); - auto right = fn5( rRectSource.Right() + aMapResSource.mnMapOfsX, + // tdf#141761 see comments above, IsEmpty() removed + auto right = rRectSource.IsWidthEmpty() ? 0 : fn5( rRectSource.Right() + aMapResSource.mnMapOfsX, aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX, aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) - aMapResDest.mnMapOfsX; - auto bottom = fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY, + auto bottom = rRectSource.IsHeightEmpty() ? 0 : fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY, aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY, aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) - aMapResDest.mnMapOfsY; - return tools::Rectangle(left, top, right, bottom); + + aRetval = tools::Rectangle(left, top, right, bottom); } + + if(rRectSource.IsWidthEmpty()) + aRetval.SetWidthEmpty(); + + if(rRectSource.IsHeightEmpty()) + aRetval.SetHeightEmpty(); + + return aRetval; } tools::Long OutputDevice::LogicToLogic( tools::Long nLongSource, -- cgit v1.2.3