sc/qa/unit/data/ods/LargeAnchorOffset.ods |binary
 sc/qa/unit/scshapetest.cxx                |   34 ++++++++++++++++++++++++++++++
 sc/source/filter/xml/xmlexprt.cxx         |    8 ++-----
 3 files changed, 37 insertions(+), 5 deletions(-)

New commits:
commit 7d5dcf5f547e29d61e788b88f7a3f7b4feafb6b2
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Jun 22 16:22:50 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Jun 22 19:28:19 2022 +0200

    Fix shape rectangle calculation
    
    At specific screen resolutions, caused failed CppunitTest_sc_shapetest:
    
      C:/lo/src/core/sc/qa/unit/scshapetest.cxx(169) : error : Assertion
      Test name: 
sc_apitest::ScShapeTest::testTdf137576_LogicRectInDefaultMeasureline
      assertion failed
      - Expression: std::abs(rExpected.Y() - rActual.Y()) <= nTolerance
      - after reload Y expected 9731 actual 10287 Tolerance 1
    
    which manifested the actual wrong position of shape written into ODF.
    Commit cd966aac6ecd8ce606ac3f2ccd602e467114ba3f
      Author Regina Henschel <rb.hensc...@t-online.de>
      Date   Fri Dec 25 19:27:51 2020 +0100
        tdf#137033 improve save of cell anchored shapes
    
    had corrected the calculation of anchor point, but the overlook was
    that in some cases of non-transformed shapes, rMyCell.maCellAddress
    may differ from pObjData->maStart. Since aSnapStartAddress could be
    not set to pObjData->maStart for such shapes, the wrong cell range
    could be calculated for resized-with-cell objects.
    
    Fix this by using pObjData->maStart whenever there is pObjData. If
    it turns out that in some cases, rMyCell.maCellAddress is needed in
    calculations before the 'if (rShape.bResizeWithCell && pObjData)',
    aSnapStartAddress should be assigned to pObjData->maStart after the
    check.
    
    Change-Id: I7e0dc834c2ffb147430fb5b2cb8bdb4dca201b3b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136285
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sc/qa/unit/data/ods/LargeAnchorOffset.ods 
b/sc/qa/unit/data/ods/LargeAnchorOffset.ods
new file mode 100644
index 000000000000..c7e44527e235
Binary files /dev/null and b/sc/qa/unit/data/ods/LargeAnchorOffset.ods differ
diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx
index 761db2da687c..dc47be21b0d3 100644
--- a/sc/qa/unit/scshapetest.cxx
+++ b/sc/qa/unit/scshapetest.cxx
@@ -71,6 +71,7 @@ public:
     void testCustomShapeCellAnchoredRotatedShape();
     void testTdf144242_Line_noSwapWH();
     void testTdf144242_OpenBezier_noSwapWH();
+    void testLargeAnchorOffset();
 
     CPPUNIT_TEST_SUITE(ScShapeTest);
     CPPUNIT_TEST(testTdf143619_validation_circle_pos);
@@ -100,6 +101,7 @@ public:
     CPPUNIT_TEST(testCustomShapeCellAnchoredRotatedShape);
     CPPUNIT_TEST(testTdf144242_Line_noSwapWH);
     CPPUNIT_TEST(testTdf144242_OpenBezier_noSwapWH);
+    CPPUNIT_TEST(testLargeAnchorOffset);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1234,6 +1236,38 @@ void 
ScShapeTest::testCustomShapeCellAnchoredRotatedShape()
     pDocSh->DoClose();
 }
 
+void ScShapeTest::testLargeAnchorOffset()
+{
+    // The example doc contains a resize-with-cell-anchored measure line
+    // with a large vertical offset that shifts the start point onto the
+    // next cell below.
+    OUString aFileURL;
+    createFileURL(u"LargeAnchorOffset.ods", aFileURL);
+    uno::Reference<css::lang::XComponent> xComponent = 
loadFromDesktop(aFileURL);
+
+    ScDocShell* pDocSh = lcl_getScDocShellWithAssert(xComponent);
+    SdrObject* pObj = lcl_getSdrObjectWithAssert(pDocSh->GetDocument(), 0);
+
+    const Point aOldPos = pObj->GetRelativePos();
+    // Just to check that it imports correctly
+    lcl_AssertPointEqualWithTolerance("before reload", { 9504, 9089 }, 
aOldPos, 1);
+
+    saveAndReload(xComponent, "calc8");
+
+    pDocSh = lcl_getScDocShellWithAssert(xComponent);
+    pObj = lcl_getSdrObjectWithAssert(pDocSh->GetDocument(), 0);
+
+    // Without the fix, this would fail:
+    //   Test name: sc_apitest::ScShapeTest::testLargeAnchorOffset
+    //   assertion failed
+    //   - Expression: std::abs(rExpected.Y() - rActual.Y()) <= nTolerance
+    //   - after reload Y expected 9089 actual 9643 Tolerance 1
+    const Point aNewPos = pObj->GetRelativePos();
+    lcl_AssertPointEqualWithTolerance("after reload", aOldPos, aNewPos, 1);
+
+    pDocSh->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(ScShapeTest);
 }
 
diff --git a/sc/source/filter/xml/xmlexprt.cxx 
b/sc/source/filter/xml/xmlexprt.cxx
index 57c041f7f5ee..8a781127035a 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -3481,14 +3481,12 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
             // end cell address of snap rect. In case of a transformed shape, 
it is not in rMyCell.
             ScAddress aSnapStartAddress = rMyCell.maCellAddress;
             ScDrawObjData* pObjData = nullptr;
-            bool bIsShapeTransformed = false;
             if (pObj)
             {
                 pObjData = ScDrawLayer::GetObjData(pObj);
-                bIsShapeTransformed = pObj->GetRotateAngle() != 0_deg100 || 
pObj->GetShearAngle() != 0_deg100;
+                if (pObjData)
+                    aSnapStartAddress = pObjData->maStart;
             }
-            if (bIsShapeTransformed && pObjData)
-                aSnapStartAddress = pObjData->maStart;
 
             // In case rows or columns are hidden above or before the snap 
rect, move the shape to the
             // position it would have, if these rows and columns are visible.
@@ -3509,7 +3507,7 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
             // tdf#137033 In case the shape is anchored "To Cell (resize with 
cell)" hiding rows or
             // columns inside the snap rect has not only changed size of the 
shape but rotate and shear
             // angle too. We resize the shape to full size. That will recover 
the original angles too.
-            if (rShape.bResizeWithCell && pObjData && pObj)
+            if (rShape.bResizeWithCell && pObjData) // implies pObj & 
aSnapStartAddress = pObjData->maStart
             {
                 // Get original size from anchor
                 const Point aSnapStartOffset = pObjData->maStartOffset;

Reply via email to