sc/qa/unit/scshapetest.cxx       |   59 +++++++++++++++++++++++++++++++++++++++
 sc/source/core/data/drwlayer.cxx |   14 +++++----
 sc/source/ui/view/drawvie3.cxx   |    8 ++++-
 3 files changed, 75 insertions(+), 6 deletions(-)

New commits:
commit 2383bb3dfe489309b1b57b95bfec56b4967610fb
Author:     Regina Henschel <[email protected]>
AuthorDate: Fri Jan 15 17:40:10 2021 +0100
Commit:     Xisco Fauli <[email protected]>
CommitDate: Tue Jan 19 11:45:18 2021 +0100

    tdf#139583 fix case rot 180deg for cell anchored shapes
    
    Method adjustAnchoredPosition() in ScDrawView::Notify() needs to
    distinguish whether an object really has a changed geometry or only
    becomes visible. The previous solution used the snap rectangle for this.
    But in the case of a 180deg rotation only the logic rectangle changes,
    not the snap rectangle. The patch extends the test to consider logic
    rectangle as well. SetCellAnchoredFromPosition is adjusted to create
    maShapeRect, which is compared to the logic rectangle.
    
    Change-Id: Iba8a173938da05178f1058ef98e9ef526cca490e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109386
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <[email protected]>
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109534

diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx
index 820f499034c8..c5089939e86f 100644
--- a/sc/qa/unit/scshapetest.cxx
+++ b/sc/qa/unit/scshapetest.cxx
@@ -20,6 +20,7 @@
 #include <svx/svdoashp.hxx>
 #include <svx/svdomeas.hxx>
 #include <svx/svdpage.hxx>
+#include <svx/svdorect.hxx>
 #include <unotools/tempfile.hxx>
 #include <vcl/keycodes.hxx>
 
@@ -40,6 +41,7 @@ public:
     ScShapeTest();
     void saveAndReload(css::uno::Reference<css::lang::XComponent>& xComponent,
                        const OUString& rFilter);
+    void testTdf139583_Rotate180deg();
     void testTdf137033_FlipHori_Resize();
     void testTdf137033_RotShear_ResizeHide();
     void testTdf137033_RotShear_Hide();
@@ -59,6 +61,7 @@ public:
     void testCustomShapeCellAnchoredRotatedShape();
 
     CPPUNIT_TEST_SUITE(ScShapeTest);
+    CPPUNIT_TEST(testTdf139583_Rotate180deg);
     CPPUNIT_TEST(testTdf137033_FlipHori_Resize);
     CPPUNIT_TEST(testTdf137033_RotShear_ResizeHide);
     CPPUNIT_TEST(testTdf137033_RotShear_Hide);
@@ -142,6 +145,62 @@ static void lcl_AssertPointEqualWithTolerance(const 
OString& sInfo, const Point
     CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), std::abs(rExpected.Y() - 
rActual.Y()) <= nTolerance);
 }
 
+void ScShapeTest::testTdf139583_Rotate180deg()
+{
+    // Load an empty document.
+    OUString aFileURL;
+    createFileURL(u"ManualColWidthRowHeight.ods", aFileURL);
+    uno::Reference<css::lang::XComponent> xComponent = 
loadFromDesktop(aFileURL);
+    CPPUNIT_ASSERT(xComponent.is());
+
+    // Get ScDocShell
+    SfxObjectShell* pFoundShell = 
SfxObjectShell::GetShellFromComponent(xComponent);
+    CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+    ScDocShell* pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+    CPPUNIT_ASSERT(pDocSh);
+
+    // Get SdrPage
+    ScDocument& rDoc = pDocSh->GetDocument();
+    ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+    CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+    SdrPage* pPage = pDrawLayer->GetPage(0);
+    CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+
+    // Insert Shape
+    const tools::Rectangle aRect(Point(3000, 4000), Size(5000, 2000));
+    SdrRectObj* pObj = new SdrRectObj(*pDrawLayer, aRect);
+    CPPUNIT_ASSERT_MESSAGE("Could not create rectangle", pObj);
+    pPage->InsertObject(pObj);
+
+    // Anchor "to cell (resize with cell)" and then rotate it by 180deg around 
center
+    // The order is important here.
+    ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, 0 /*SCTAB*/, true 
/*bResizeWithCell*/);
+    pObj->Rotate(aRect.Center(), 18000.0, 0.0, -1.0);
+
+    // Save and reload.
+    saveAndReload(xComponent, "calc8");
+    CPPUNIT_ASSERT(xComponent);
+
+    // Get ScDocShell
+    pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+    CPPUNIT_ASSERT_MESSAGE("Reload: Failed to access document shell", 
pFoundShell);
+    pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+    CPPUNIT_ASSERT(pDocSh);
+
+    // Get document and object
+    ScDocument& rDoc2 = pDocSh->GetDocument();
+    pDrawLayer = rDoc2.GetDrawLayer();
+    CPPUNIT_ASSERT_MESSAGE("Reload: No ScDrawLayer", pDrawLayer);
+    pPage = pDrawLayer->GetPage(0);
+    CPPUNIT_ASSERT_MESSAGE("Reload: No draw page", pPage);
+    pObj = dynamic_cast<SdrRectObj*>(pPage->GetObj(0));
+    CPPUNIT_ASSERT_MESSAGE("Reload: Shape no longer exists", pObj);
+
+    //  Without the fix in place, the shape would have nearly zero size.
+    lcl_AssertRectEqualWithTolerance("Show: Object geometry should not 
change", aRect,
+                                     pObj->GetSnapRect(), 1);
+}
+
 void ScShapeTest::testTdf137033_FlipHori_Resize()
 {
     // Load a document, which has a rotated custom shape, which is horizontal 
flipped. Error was, that
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index f041c5d776b6..fffe3e75d085 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -890,7 +890,6 @@ void ScDrawLayer::InitializeCellAnchoredObj(SdrObject* 
pObj, ScDrawObjData& rDat
     // rNoRotatedAnchor refers in its start and end addresses and its start 
and end offsets to
     // the logic rectangle of the object. The values are so, as if no hidden 
columns and rows
     // exists and if it is a LTR sheet. These values are directly used for XML 
in ODF file.
-    // ToDO: Check whether its maShapeRect member is actually used.
     ScDrawObjData& rNoRotatedAnchor = *GetNonRotatedObjData(pObj, true 
/*bCreate*/);
 
     // From XML import, rData contains temporarily the anchor information as 
they are given in
@@ -962,8 +961,9 @@ void ScDrawLayer::InitializeCellAnchoredObj(SdrObject* 
pObj, ScDrawObjData& rDat
                                         true /*bUseLogicRect*/);
     }
 
-    // Make sure maShapeRect of rNoRotatedAnchor is not empty. ToDo: Really 
used?
-    // Currently ScExportTest::testMoveCellAnchoredShapesODS checks it.
+    // Make sure maShapeRect of rNoRotatedAnchor is not empty. Method 
ScDrawView::Notify()
+    // needs it to detect a change in object geometry. For example a 180deg 
rotation effects only
+    // logic rect.
     rNoRotatedAnchor.setShapeRect(GetDocument(), pObj->GetLogicRect(), true);
 
     // Start and end addresses and offsets in rData refer to the actual snap 
rectangle of the
@@ -1180,8 +1180,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, 
ScDrawObjData& rData, bool bNegati
                     pObj->SetSnapRect(rData.getShapeRect());
 
                 // update 'unrotated anchor' it's the anchor we persist, it 
must be kept in sync
-                // with the normal Anchor
-                // ToDo: Is maShapeRect of rNoRotatedAnchor used at all?
+                // with the normal Anchor.
                 ResizeLastRectFromAnchor(pObj, rNoRotatedAnchor, true, 
bNegativePage, bCanResize);
             }
         }
@@ -2247,6 +2246,11 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject 
&rObj, const ScDocument
 
     aVisAnchor.mbResizeWithCell = bResizeWithCell;
     SetVisualCellAnchored( rObj, aVisAnchor );
+    // And update maShapeRect. It is used in adjustAnchoredPosition() in 
ScDrawView::Notify().
+    if (ScDrawObjData* pAnchor = GetNonRotatedObjData(&rObj))
+    {
+        pAnchor->setShapeRect(&rDoc, rObj.GetSnapRect());
+    }
 }
 
 void ScDrawLayer::GetCellAnchorFromPosition(
diff --git a/sc/source/ui/view/drawvie3.cxx b/sc/source/ui/view/drawvie3.cxx
index f52e5947cbfa..4e2928b0569d 100644
--- a/sc/source/ui/view/drawvie3.cxx
+++ b/sc/source/ui/view/drawvie3.cxx
@@ -176,7 +176,13 @@ void adjustAnchoredPosition(const SdrHint& rHint, const 
ScDocument& rDoc, SCTAB
 
     if (pAnchor->meType == ScDrawObjData::CellNote)
         return;
-    if (lcl_AreRectanglesApproxEqual(pAnchor->getShapeRect(), 
pObj->GetSnapRect()))
+
+    // SetCellAnchoredFromPosition has to be called only if shape geometry has 
been changed, and not
+    // if only shape visibilty has been changed. It is not enough to test 
shape rect, because e.g. a
+    // 180deg rotation changes only the logic rect (tdf#139583).
+    ScDrawObjData& rNoRotatedAnchor = *ScDrawLayer::GetNonRotatedObjData(pObj, 
true /*bCreate*/);
+    if (lcl_AreRectanglesApproxEqual(pAnchor->getShapeRect(), 
pObj->GetSnapRect())
+        && lcl_AreRectanglesApproxEqual(rNoRotatedAnchor.getShapeRect(), 
pObj->GetLogicRect()))
         return;
 
     if (pAnchor->maStart.Tab() != nTab)
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to