[Libreoffice-commits] core.git: sc/inc sc/qa sc/source

Samuel Mehrbrodt Samuel.Mehrbrodt at cib.de
Mon Mar 12 23:24:06 UTC 2018


 sc/inc/drwlayer.hxx                    |    1 
 sc/inc/userdat.hxx                     |   21 ++++
 sc/qa/unit/subsequent_export-test.cxx  |   22 ++--
 sc/qa/unit/subsequent_filters-test.cxx |    2 
 sc/qa/unit/ucalc.cxx                   |    8 +
 sc/source/core/data/drwlayer.cxx       |  154 +++++++++++++++++++++++++--------
 sc/source/core/data/table5.cxx         |   10 ++
 sc/source/ui/view/drawvie3.cxx         |    2 
 8 files changed, 167 insertions(+), 53 deletions(-)

New commits:
commit 4f29ce6a67b81e7f28e1c86d60ff15ec1d180661
Author: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
Date:   Tue Feb 27 16:56:44 2018 +0100

    tdf#114552 Improve image scaling in Calc
    
    When anchor type "To cell (resize with cell)" is selected, we do now::
    
    1. Consider aspect ratio when scaling graphic objects with cell
       This only works when the image fits into one cell.
       When the image is over multiple cells, we need to respect the end
       anchor, so we need to keep the existing behavior (no aspect ratio considered).
    2. Always scale images if anchor type is "resize with cell"
       Previously it would only scale if the image is larger than the cell.
       Now we always enlarge the image if the cell is enlarged, and shrink
       the image if the cell is shrinked _and_ the image no longer fits
       into the shrinked cell
    
    Change-Id: Ib2a24819d0058bcebce73ea97bbf70a963d74584
    Reviewed-on: https://gerrit.libreoffice.org/50451
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/inc/drwlayer.hxx b/sc/inc/drwlayer.hxx
index 123463855a25..5f695160cc42 100644
--- a/sc/inc/drwlayer.hxx
+++ b/sc/inc/drwlayer.hxx
@@ -184,6 +184,7 @@ public:
     static void             SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab, bool bResizeWithCell );
     static void             UpdateCellAnchorFromPositionEnd( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect = true );
     static ScAnchorType     GetAnchorType( const SdrObject& );
+    std::vector<SdrObject*> GetObjectsAnchoredToRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow);
     std::map<SCROW, std::vector<SdrObject*>> GetObjectsAnchoredToRange(SCTAB nTab, SCCOL nCol, SCROW nStartRow, SCROW nEndRow);
     bool HasObjectsAnchoredInRange(ScRange& rRange);
     void MoveObject(SdrObject* pObj, ScAddress& rNewPosition);
diff --git a/sc/inc/userdat.hxx b/sc/inc/userdat.hxx
index fd903dfc1010..04c6893faded 100644
--- a/sc/inc/userdat.hxx
+++ b/sc/inc/userdat.hxx
@@ -25,6 +25,7 @@
 #include <svtools/imap.hxx>
 #include "global.hxx"
 #include "address.hxx"
+#include "drwlayer.hxx"
 
 // Object IDs for UserData
 #define SC_UD_OBJDATA       1
@@ -41,13 +42,31 @@ public:
     Point               maStartOffset;
     Point               maEndOffset;
     Type                meType;
-    tools::Rectangle           maLastRect;
     bool                mbResizeWithCell = false;
+    bool                mbWasInHiddenRow = false;
 
     explicit            ScDrawObjData();
 
+    tools::Rectangle getShapeRect() { return maShapeRect; };
+    tools::Rectangle getLastCellRect() { return maLastCellRect; };
+    void setShapeRect(const ScDocument* rDoc, tools::Rectangle rNewRect, bool bIsVisible=true)
+    {
+        // bIsVisible should be false when the object is hidden obviously. we dont want to store the old cell rect in that
+        // case because it will have height=0
+        if (maStart.IsValid() && mbResizeWithCell && bIsVisible)
+            maLastCellRect = ScDrawLayer::GetCellRect(*rDoc, maStart, true);
+        maShapeRect = rNewRect;
+        mbWasInHiddenRow = !bIsVisible;
+    };
+
 private:
      virtual ScDrawObjData* Clone( SdrObject* pObj ) const override;
+
+    // Stores the last cell rect this shape was anchored to.
+    // Needed when the cell is resized to resize the image accordingly.
+    tools::Rectangle maLastCellRect;
+    // Stores the rect of the shape to which this ScDrawObjData belongs.
+    tools::Rectangle maShapeRect;
 };
 
 class ScIMapInfo : public SdrObjUserData
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 688378166014..26b925d14a16 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -2166,7 +2166,7 @@ void ScExportTest::testCellAnchoredGroupXLS()
     ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
     CPPUNIT_ASSERT_MESSAGE("Upper left of bounding rectangle should be nonnegative.",
-        pData->maLastRect.Left() >= 0 || pData->maLastRect.Top() >= 0);
+        pData->getShapeRect().Left() >= 0 || pData->getShapeRect().Top() >= 0);
     xDocSh->DoClose();
 }
 
@@ -3529,7 +3529,7 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
     // Get anchor data
     ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
 
     ScAddress aDataStart = pData->maStart;
     ScAddress aDataEnd   = pData->maEnd;
@@ -3537,7 +3537,7 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
     // Get non rotated anchor data
     ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
 
     ScAddress aNDataStart = pNData->maStart;
     ScAddress aNDataEnd   = pNData->maEnd;
@@ -3550,12 +3550,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
     // Get anchor data
     pData = ScDrawLayer::GetObjData(pObj);
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
 
     // Get non rotated anchor data
     pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
 
     // Check if data has moved to new rows
     CPPUNIT_ASSERT_EQUAL( pData->maStart.Row(), aDataStart.Row() + 2 );
@@ -3591,12 +3591,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
     // Get anchor data
     pData = ScDrawLayer::GetObjData(pObj);
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
 
     // Get non rotated anchor data
     pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
 
     // Check if data after save it
     CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
@@ -3611,12 +3611,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
     // Get anchor data
     pData = ScDrawLayer::GetObjData(pObj);
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
 
     // Get non rotated anchor data
     pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
 
     // Check if data has moved to new rows
     CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1));
@@ -3652,12 +3652,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
     // Get anchor data
     pData = ScDrawLayer::GetObjData(pObj);
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
 
     // Get non rotated anchor data
     pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
     CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
-    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+    CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
 
     // Check if data after save it
     CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 3ec2982ada04..2e876434ce49 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -1761,7 +1761,7 @@ void ScFiltersTest::testCellAnchoredShapesODS()
         CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
         ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
         CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
-        CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+        CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
     }
 
     xDocSh->DoClose();
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 2b03df58ad9f..0f60db22a8ba 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2732,13 +2732,17 @@ void Test::testGraphicsInGroup()
 
         m_pDoc->ShowRows(0, 100, 0, false);
         m_pDoc->SetDrawPageSize(0);
+
+        const long TOLERANCE = 30; //30 hmm
+
         CPPUNIT_ASSERT_MESSAGE("Left and Right should be unchanged",
-            aOrigRect.Left() == rNewRect.Left() && aOrigRect.Right() == rNewRect.Right());
+            testEqualsWithTolerance(aOrigRect.Left(), rNewRect.Left(), TOLERANCE) &&
+            testEqualsWithTolerance(aOrigRect.Right(), rNewRect.Right(), TOLERANCE));
         CPPUNIT_ASSERT_MESSAGE("Height should be minimum allowed height",
             (rNewRect.Bottom() - rNewRect.Top()) <= 1);
         m_pDoc->ShowRows(0, 100, 0, true);
         m_pDoc->SetDrawPageSize(0);
-        CPPUNIT_ASSERT_EQUAL_MESSAGE("Should not change when page anchored",
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Should not change when cell anchored",
                                const_cast<const tools::Rectangle &>(aOrigRect), rNewRect);
     }
 
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 341444525220..3cadfdb55979 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -624,40 +624,96 @@ namespace
             static_cast<long>(aRange.getMaxX()), static_cast<long>(aRange.getMaxY()));
     }
 }
-void ScDrawLayer::ResizeLastRectFromAnchor( const SdrObject* pObj, ScDrawObjData& rData, bool bUseLogicRect, bool bNegativePage, bool bCanResize, bool bHiddenAsZero )
+
+void ScDrawLayer::ResizeLastRectFromAnchor(const SdrObject* pObj, ScDrawObjData& rData,
+                                           bool bUseLogicRect, bool bNegativePage, bool bCanResize,
+                                           bool bHiddenAsZero)
 {
-    rData.maLastRect = ( bUseLogicRect ? pObj->GetLogicRect() : pObj->GetSnapRect() );
+    tools::Rectangle aRect = bUseLogicRect ? pObj->GetLogicRect() : pObj->GetSnapRect();
     SCCOL nCol1 = rData.maStart.Col();
     SCROW nRow1 = rData.maStart.Row();
     SCTAB nTab1 = rData.maStart.Tab();
     SCCOL nCol2 = rData.maEnd.Col();
     SCROW nRow2 = rData.maEnd.Row();
     SCTAB nTab2 = rData.maEnd.Tab();
-    Point aPos( pDoc->GetColOffset( nCol1, nTab1, bHiddenAsZero ), pDoc->GetRowOffset( nRow1, nTab1, bHiddenAsZero ) );
-    aPos.setX(TwipsToHmm( aPos.X() ));
-    aPos.setY(TwipsToHmm( aPos.Y() ));
+    Point aPos(pDoc->GetColOffset(nCol1, nTab1, bHiddenAsZero),
+               pDoc->GetRowOffset(nRow1, nTab1, bHiddenAsZero));
+    aPos.setX(TwipsToHmm(aPos.X()));
+    aPos.setY(TwipsToHmm(aPos.Y()));
     aPos += lcl_calcAvailableDiff(*pDoc, nCol1, nRow1, nTab1, rData.maStartOffset);
+    aRect.SetPos(aPos);
 
-    if( bCanResize )
+    if (bCanResize)
     {
-        Point aEnd( pDoc->GetColOffset( nCol2, nTab2, bHiddenAsZero ), pDoc->GetRowOffset( nRow2, nTab2, bHiddenAsZero ) );
-        aEnd.setX(TwipsToHmm( aEnd.X() ));
-        aEnd.setY(TwipsToHmm( aEnd.Y() ));
-        aEnd += lcl_calcAvailableDiff(*pDoc, nCol2, nRow2, nTab2, rData.maEndOffset);
+        tools::Rectangle aLastCellRect = rData.getLastCellRect();
 
-        tools::Rectangle aNew = tools::Rectangle( aPos, aEnd );
-        if ( bNegativePage )
-            MirrorRectRTL( aNew );
+        // If the row was hidden before, or we don't have a valid cell rect, calculate the
+        // new rect based on the end point.
+        // Also when the end point is set, we need to consider it.
+        if (rData.mbWasInHiddenRow || aLastCellRect.IsEmpty() || nRow1 != nRow2 || nCol1 != nCol2)
+        {
+            Point aEnd(pDoc->GetColOffset(nCol2, nTab2, bHiddenAsZero),
+                       pDoc->GetRowOffset(nRow2, nTab2, bHiddenAsZero));
+            aEnd.setX(TwipsToHmm(aEnd.X()));
+            aEnd.setY(TwipsToHmm(aEnd.Y()));
+            aEnd += lcl_calcAvailableDiff(*pDoc, nCol2, nRow2, nTab2, rData.maEndOffset);
 
-        rData.maLastRect = lcl_makeSafeRectangle(aNew);
-    }
-    else
-    {
-        if ( bNegativePage )
-            aPos.setX( -aPos.X() - rData.maLastRect.GetWidth() );
-        // shouldn't we initialise maLastRect with the object rectangle ?
-        rData.maLastRect.SetPos( aPos );
+            aRect = tools::Rectangle(aPos, aEnd);
+        }
+        else if (!aLastCellRect.IsEmpty())
+        {
+            // We calculate based on the last cell rect to be able to scale the image
+            // as much as the cell was scaled.
+            // Still, we keep the image in its current cell (to keep start anchor == end anchor)
+            tools::Rectangle aCurrentCellRect = GetCellRect(*GetDocument(), rData.maStart, true);
+            double fWidthFactor = static_cast<double>(aCurrentCellRect.GetWidth())
+                                  / static_cast<double>(aLastCellRect.GetWidth());
+            double fHeightFactor = static_cast<double>(aCurrentCellRect.GetHeight())
+                                   / static_cast<double>(aLastCellRect.GetHeight());
+
+            bool bIsGrowingLarger = aLastCellRect.GetWidth() * aLastCellRect.GetHeight()
+                                    < aCurrentCellRect.GetWidth() * aCurrentCellRect.GetHeight();
+
+            if (pObj->shouldKeepAspectRatio())
+            {
+                tools::Rectangle aRectIncludingOffset = aRect;
+                aRectIncludingOffset.setWidth(aRect.GetWidth() + rData.maStartOffset.X());
+                aRectIncludingOffset.setHeight(aRect.GetHeight() + rData.maStartOffset.Y());
+                double fMaxWidthFactor = static_cast<double>(aCurrentCellRect.GetWidth())
+                                         / static_cast<double>(aRectIncludingOffset.GetWidth());
+                double fMaxHeightFactor = static_cast<double>(aCurrentCellRect.GetHeight())
+                                          / static_cast<double>(aRectIncludingOffset.GetHeight());
+                double fMaxFactor = std::min(fMaxHeightFactor, fMaxWidthFactor);
+
+                if (bIsGrowingLarger) // cell is growing larger
+                {
+                    // To actually grow the image, we need to take the max
+                    fWidthFactor = fHeightFactor = std::max(fWidthFactor, fHeightFactor);
+                    // But we don't want the image to become larger than the current cell
+                    fWidthFactor = fHeightFactor = std::min(fWidthFactor, fMaxFactor);
+                }
+                else // cell is growing smaller, take the min
+                {
+                    fWidthFactor = fHeightFactor = std::min(fWidthFactor, fHeightFactor);
+                }
+            }
+
+            // When shrinking the cell, and the image still fits in the smaller cell, don't resize it at all
+            if (bIsGrowingLarger
+                || rData.getShapeRect().GetUnion(aCurrentCellRect) != aCurrentCellRect)
+            {
+                aRect.setWidth(
+                    rtl::math::round(static_cast<double>(aRect.GetWidth()) * fWidthFactor));
+                aRect.setHeight(
+                    rtl::math::round(static_cast<double>(aRect.GetHeight()) * fHeightFactor));
+            }
+        }
     }
+
+    if (bNegativePage)
+        MirrorRectRTL(aRect);
+
+    rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect), pObj->IsVisible());
 }
 
 void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos )
@@ -695,7 +751,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
     if (rData.meType == ScDrawObjData::ValidationCircle)
     {
         // Validation circle for detective.
-        rData.maLastRect = pObj->GetLogicRect();
+        rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
 
         Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
         aPos.setX(TwipsToHmm( aPos.X() ));
@@ -717,13 +773,13 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
         {
             if (bRecording)
                 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
-            rData.maLastRect = lcl_makeSafeRectangle(aRect);
-            pObj->SetLogicRect(rData.maLastRect);
+            rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect));
+            pObj->SetLogicRect(rData.getShapeRect());
         }
     }
     else if (rData.meType == ScDrawObjData::DetectiveArrow)
     {
-        rData.maLastRect = pObj->GetLogicRect();
+        rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
         basegfx::B2DPolygon aCalcPoly;
         Point aOrigStartPos(pObj->GetPoint(0));
         Point aOrigEndPos(pObj->GetPoint(1));
@@ -750,7 +806,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
                 if (bRecording)
                     AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
 
-                rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos);
+                rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos));
                 pObj->SetPoint( aStartPos, 0 );
             }
 
@@ -766,7 +822,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
                     if (bRecording)
                         AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
 
-                    rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos);
+                    rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos));
                     pObj->SetPoint( aEndPos, 1 );
                 }
             }
@@ -788,7 +844,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
                 if (bRecording)
                     AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
 
-                rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos);
+                rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos));
                 pObj->SetPoint( aEndPos, 1 );
             }
 
@@ -806,7 +862,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
                     if (bRecording)
                         AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
 
-                    rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos);
+                    rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos));
                     pObj->SetPoint( aStartPos, 0 );
                 }
             }
@@ -821,7 +877,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
 
         //First time positioning, must be able to at least move it
         ScDrawObjData& rNoRotatedAnchor = *GetNonRotatedObjData( pObj, true );
-        if (rData.maLastRect.IsEmpty())
+        if (rData.getShapeRect().IsEmpty())
         {
             // Every shape it is saved with an negative offset relative to cell
             ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType(*pObj);
@@ -881,7 +937,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
             // is guaranteed to get consistent results)
             ResizeLastRectFromAnchor( pObj, rData, true, bNegativePage, bCanResize, false );
             // aFullRect contains the unrotated size and position of the shape (regardless of any hidden row/columns)
-            tools::Rectangle aFullRect = rData.maLastRect;
+            tools::Rectangle aFullRect = rData.getShapeRect();
 
             // get current size and position from the anchor for use later
             ResizeLastRectFromAnchor( pObj, rNoRotatedAnchor, true, bNegativePage, bCanResize );
@@ -894,7 +950,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
             // an Anchor based on the SnapRect ( which is what you see on the screen )
             ScDrawLayer::GetCellAnchorFromPosition( *pObj, rData, *pDoc, nTab1, false, false );
             // reset shape to true 'maybe affected by hidden rows/cols' size calculated previously
-            pObj->SetLogicRect(rNoRotatedAnchor.maLastRect);
+            pObj->SetLogicRect(rNoRotatedAnchor.getShapeRect());
         }
 
         // update anchor with snap rect
@@ -902,7 +958,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
 
         if( bCanResize )
         {
-            tools::Rectangle aNew = rData.maLastRect;
+            tools::Rectangle aNew = rData.getShapeRect();
 
             if ( pObj->GetSnapRect() != aNew )
             {
@@ -924,8 +980,8 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
                 }
                 // order of these lines is important, modify rData.maLastRect carefully it is used as both
                 // a value and a flag for initialisation
-                rData.maLastRect = lcl_makeSafeRectangle(rData.maLastRect);
-                pObj->SetSnapRect(rData.maLastRect);
+                rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(rData.getShapeRect()), pObj->IsVisible());
+                pObj->SetSnapRect(rData.getShapeRect());
                 // update 'unrotated anchor' it's the anchor we persist, it must be kept in sync
                 // with the normal Anchor
                 ResizeLastRectFromAnchor( pObj, rNoRotatedAnchor, true, bNegativePage, bCanResize );
@@ -933,7 +989,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
         }
         else
         {
-            Point aPos( rData.maLastRect.getX(), rData.maLastRect.getY() );
+            Point aPos( rData.getShapeRect().getX(), rData.getShapeRect().getY() );
             if ( pObj->GetRelativePos() != aPos )
             {
                 if (bRecording)
@@ -1922,7 +1978,7 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument
     // doing an initialisation hack
     if ( ScDrawObjData* pAnchor = GetObjData( &rObj ) )
     {
-        pAnchor->maLastRect = rObj.GetSnapRect();
+        pAnchor->setShapeRect(&rDoc, rObj.GetSnapRect());
     }
 }
 
@@ -2012,6 +2068,30 @@ ScAnchorType ScDrawLayer::GetAnchorType( const SdrObject &rObj )
     return SCA_CELL;
 }
 
+std::vector<SdrObject*>
+ScDrawLayer::GetObjectsAnchoredToRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow)
+{
+    SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
+    if (!pPage || pPage->GetObjCount() < 1)
+        return std::vector<SdrObject*>();
+
+    std::vector<SdrObject*> aObjects;
+    SdrObjListIter aIter( *pPage, SdrIterMode::Flat );
+    SdrObject* pObject = aIter.Next();
+    ScRange aRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab);
+    while (pObject)
+    {
+        if (!dynamic_cast<SdrCaptionObj*>(pObject)) // Caption objects are handled differently
+        {
+            ScDrawObjData* pObjData = GetObjData(pObject);
+            if (pObjData && aRange.In(pObjData->maStart))
+                aObjects.push_back(pObject);
+        }
+        pObject = aIter.Next();
+    }
+    return aObjects;
+}
+
 std::map<SCROW, std::vector<SdrObject*>>
 ScDrawLayer::GetObjectsAnchoredToRange(SCTAB nTab, SCCOL nCol, SCROW nStartRow, SCROW nEndRow)
 {
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
index bae5895ec2a5..41de2787dbef 100644
--- a/sc/source/core/data/table5.cxx
+++ b/sc/source/core/data/table5.cxx
@@ -586,6 +586,16 @@ bool ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
     else
         bChanged = mpHiddenRows->setFalse(nStartRow, nEndRow);
 
+    std::vector<SdrObject*> aRowDrawObjects;
+    ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+    if (pDrawLayer) {
+        aRowDrawObjects = pDrawLayer->GetObjectsAnchoredToRows(GetTab(), nStartRow, nEndRow);
+        for (auto aObj : aRowDrawObjects)
+        {
+            aObj->SetVisible(!bHidden);
+        }
+    }
+
     if (bChanged)
     {
         SetStreamValid(false);
diff --git a/sc/source/ui/view/drawvie3.cxx b/sc/source/ui/view/drawvie3.cxx
index b49acf847132..4be43b1354d1 100644
--- a/sc/source/ui/view/drawvie3.cxx
+++ b/sc/source/ui/view/drawvie3.cxx
@@ -159,7 +159,7 @@ void adjustAnchoredPosition(const SdrHint& rHint, const ScDocument& rDoc, SCTAB
     if (pAnchor->meType == ScDrawObjData::CellNote)
         return;
 
-    if (pAnchor->maLastRect == pObj->GetSnapRect())
+    if (pAnchor->getShapeRect() == pObj->GetSnapRect())
         return;
 
     if (pAnchor->maStart.Tab() != nTab)


More information about the Libreoffice-commits mailing list