summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorRegina Henschel <rb.henschel@t-online.de>2020-12-25 19:27:51 +0100
committerRegina Henschel <rb.henschel@t-online.de>2020-12-28 15:05:38 +0100
commitcd966aac6ecd8ce606ac3f2ccd602e467114ba3f (patch)
treeb15a524e3238d98cc203959ef9298fb363bc0596 /sc
parentd7f3e68f849d11f6e02019b4a788982cae71d37b (diff)
tdf#137033 improve save of cell anchored shapes
Error was, that rotated or sheared shapes got wrong position or size on save and reload in some cases. These situations should be correct now: A) Hide or show row/col above or before shape. It uses snap rectangle now. Previous solution failed, if hidden row/col is after snap rectangle left/top and before logic rectangle left/top. B) Repair ScShapeTest::testTdf137576_LogicRectInDefaultMeasureline() which would not have failed. SetColHidden() does only set the information, but does not trigger recalculation itself. C) Add solution for case shape is anchored 'resize with cell' and hidden row/col is covered by the shape. D) In case custom shape is anchored 'resize with cell' and mirrored horizontal, the translation value is wrong. I have not found the reason yet. So I have added a solution here for writing the xml markup correctly. It should work with correct translation values too. In all cases the solution does not consider right-to-left sheets. RTL sheets are still ToDo's. Change-Id: Ia15a05b637d12d9798bbc8ffca52f606058deb87 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108377 Reviewed-by: Regina Henschel <rb.henschel@t-online.de> Tested-by: Regina Henschel <rb.henschel@t-online.de>
Diffstat (limited to 'sc')
-rw-r--r--sc/qa/unit/data/ods/tdf137033_FlipHoriRotCustomShape.odsbin0 -> 9008 bytes
-rw-r--r--sc/qa/unit/data/ods/tdf137033_RotShearCellAnchor.odsbin0 -> 9145 bytes
-rw-r--r--sc/qa/unit/data/ods/tdf137033_RotShearResizeAnchor.odsbin0 -> 9369 bytes
-rw-r--r--sc/qa/unit/scshapetest.cxx207
-rw-r--r--sc/source/filter/xml/xmlexprt.cxx104
5 files changed, 290 insertions, 21 deletions
diff --git a/sc/qa/unit/data/ods/tdf137033_FlipHoriRotCustomShape.ods b/sc/qa/unit/data/ods/tdf137033_FlipHoriRotCustomShape.ods
new file mode 100644
index 000000000000..8a375b313962
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf137033_FlipHoriRotCustomShape.ods
Binary files differ
diff --git a/sc/qa/unit/data/ods/tdf137033_RotShearCellAnchor.ods b/sc/qa/unit/data/ods/tdf137033_RotShearCellAnchor.ods
new file mode 100644
index 000000000000..df39ab15012f
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf137033_RotShearCellAnchor.ods
Binary files differ
diff --git a/sc/qa/unit/data/ods/tdf137033_RotShearResizeAnchor.ods b/sc/qa/unit/data/ods/tdf137033_RotShearResizeAnchor.ods
new file mode 100644
index 000000000000..2f617030e69a
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf137033_RotShearResizeAnchor.ods
Binary files differ
diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx
index c13ec7189622..d07f4f337977 100644
--- a/sc/qa/unit/scshapetest.cxx
+++ b/sc/qa/unit/scshapetest.cxx
@@ -37,6 +37,9 @@ public:
ScShapeTest();
void saveAndReload(css::uno::Reference<css::lang::XComponent>& xComponent,
const OUString& rFilter);
+ void testTdf137033_FlipHori_Resize();
+ void testTdf137033_RotShear_ResizeHide();
+ void testTdf137033_RotShear_Hide();
void testTdf137576_LogicRectInDefaultMeasureline();
void testTdf137576_LogicRectInNewMeasureline();
void testMeasurelineHideColSave();
@@ -50,6 +53,9 @@ public:
void testCustomShapeCellAnchoredRotatedShape();
CPPUNIT_TEST_SUITE(ScShapeTest);
+ CPPUNIT_TEST(testTdf137033_FlipHori_Resize);
+ CPPUNIT_TEST(testTdf137033_RotShear_ResizeHide);
+ CPPUNIT_TEST(testTdf137033_RotShear_Hide);
CPPUNIT_TEST(testTdf137576_LogicRectInDefaultMeasureline);
CPPUNIT_TEST(testTdf137576_LogicRectInNewMeasureline);
CPPUNIT_TEST(testMeasurelineHideColSave);
@@ -127,6 +133,191 @@ static void lcl_AssertPointEqualWithTolerance(const OString& sInfo, const Point
CPPUNIT_ASSERT_MESSAGE(sMsg.getStr(), std::abs(rExpected.Y() - rActual.Y()) <= nTolerance);
}
+void ScShapeTest::testTdf137033_FlipHori_Resize()
+{
+ // Load a document, which has a rotated custom shape, which is horizontal flipped. Error was, that
+ // if such shape was anchored "resize with cell", then after save and reload it was destorted.
+ OUString aFileURL;
+ createFileURL("tdf137033_FlipHoriRotCustomShape.ods", aFileURL);
+ uno::Reference<css::lang::XComponent> xComponent = loadFromDesktop(aFileURL);
+ CPPUNIT_ASSERT(xComponent.is());
+
+ // Get document
+ SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShell* pDocSh = static_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+ ScDocument& rDoc = pDocSh->GetDocument();
+
+ // Get shape
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ const SdrPage* pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+ SdrObjCustomShape* pObj = static_cast<SdrObjCustomShape*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("Load: custom shape not found", pObj);
+
+ // Verify shape is correctly loaded. Then set shape to "resize with cell".
+ tools::Rectangle aSnapRect(pObj->GetSnapRect());
+ const tools::Rectangle aExpectRect(Point(4998, 7000), Size(9644, 6723));
+ lcl_AssertRectEqualWithTolerance("Load, wrong pos or size: ", aExpectRect, aSnapRect, 1);
+ ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, 0 /*SCTAB*/, true /*bResizeWithCell*/);
+
+ // Save and reload.
+ saveAndReload(xComponent, "calc8");
+ CPPUNIT_ASSERT(xComponent);
+
+ // Get document
+ pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ pDocSh = static_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+ ScDocument& rDoc2 = pDocSh->GetDocument();
+
+ // Get shape
+ pDrawLayer = rDoc2.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+ pObj = static_cast<SdrObjCustomShape*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("Reload: custom shape not found", pObj);
+
+ // Check shape has the original geometry, besides rounding and unit conversion errors
+ aSnapRect = pObj->GetSnapRect();
+ lcl_AssertRectEqualWithTolerance("Reload, wrong pos or size: ", aExpectRect, aSnapRect, 1);
+
+ pDocSh->DoClose();
+}
+
+void ScShapeTest::testTdf137033_RotShear_ResizeHide()
+{
+ // For rotated or sheared shapes anchored "To Cell (resize with cell) hiding rows or columns will
+ // not only change size but rotation and shear angle too. Error was, that not the original angles
+ // of the full sized shape were written to file but the changed one.
+
+ // Load a document, which has a rotated and sheared shape, anchored to cell with resize.
+ OUString aFileURL;
+ createFileURL("tdf137033_RotShearResizeAnchor.ods", aFileURL);
+ uno::Reference<css::lang::XComponent> xComponent = loadFromDesktop(aFileURL);
+ CPPUNIT_ASSERT(xComponent.is());
+
+ // Get document
+ SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShell* pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+ ScDocument& rDoc = pDocSh->GetDocument();
+
+ // Hide rows 4 and 5 (UI number), which are inside the shape and thus change shape geometry
+ rDoc.SetRowHidden(3, 4, 0, true);
+ rDoc.SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
+
+ // Get shape
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ const SdrPage* pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+ SdrObject* pObj = pPage->GetObj(0);
+ CPPUNIT_ASSERT_MESSAGE("No object found", pObj);
+
+ // Verify hiding has changed shape geometry as expected
+ tools::Rectangle aSnapRect(pObj->GetSnapRect());
+ tools::Long aRotateAngle(pObj->GetRotateAngle());
+ tools::Long aShearAngle(pObj->GetShearAngle());
+ // mathematical exact would be Point(3868, 4795), Size(9763, 1909)
+ // current values as of LO 7.2
+ const tools::Rectangle aExpectRect(Point(3871, 4796), Size(9764, 1910));
+ const tools::Long aExpectRotateAngle(20923);
+ const tools::Long aExpectShearAngle(-6572);
+ CPPUNIT_ASSERT_MESSAGE("Hide rows, shear angle: ", abs(aShearAngle - aExpectShearAngle) <= 1);
+ CPPUNIT_ASSERT_MESSAGE("Hide rows, rotate angle: ",
+ abs(aRotateAngle - aExpectRotateAngle) <= 1);
+ lcl_AssertRectEqualWithTolerance("Reload: wrong pos or size", aExpectRect, aSnapRect, 1);
+
+ // Save and reload.
+ saveAndReload(xComponent, "calc8");
+ CPPUNIT_ASSERT(xComponent);
+
+ // Get document
+ pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+ ScDocument& rDoc2 = pDocSh->GetDocument();
+
+ // Get shape
+ pDrawLayer = rDoc2.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+ pObj = pPage->GetObj(0);
+ CPPUNIT_ASSERT_MESSAGE("No object found", pObj);
+
+ // Check shape has the original geometry, besides heavy rounding and unit conversion errors
+ aSnapRect = pObj->GetSnapRect();
+ aRotateAngle = pObj->GetRotateAngle();
+ aShearAngle = pObj->GetShearAngle();
+ CPPUNIT_ASSERT_MESSAGE("Reload, shear angle: ", abs(aShearAngle - aExpectShearAngle) <= 3);
+ CPPUNIT_ASSERT_MESSAGE("Reload, rotate angle: ", abs(aRotateAngle - aExpectRotateAngle) <= 3);
+ lcl_AssertRectEqualWithTolerance("Reload: wrong pos or size", aExpectRect, aSnapRect, 4);
+
+ pDocSh->DoClose();
+}
+
+void ScShapeTest::testTdf137033_RotShear_Hide()
+{
+ // Hiding row or columns affect cell anchored shape based on their snap rectangle. The first
+ // attempt to fix lost position has used the logic rect instead. For rotated or sheared shape it
+ // makes a difference.
+
+ // Load a document, which has a rotated and sheared shape, anchored to cell, without resize.
+ OUString aFileURL;
+ createFileURL("tdf137033_RotShearCellAnchor.ods", aFileURL);
+ uno::Reference<css::lang::XComponent> xComponent = loadFromDesktop(aFileURL);
+ CPPUNIT_ASSERT(xComponent.is());
+
+ // Get document
+ SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShell* pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+ ScDocument& rDoc = pDocSh->GetDocument();
+
+ // Hide column C, which is left from logic rect, but right from left edge of snap rect
+ rDoc.SetColHidden(2, 2, 0, true);
+ rDoc.SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
+
+ // Save and reload.
+ saveAndReload(xComponent, "calc8");
+ CPPUNIT_ASSERT(xComponent);
+
+ // Get document
+ pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ pDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
+ CPPUNIT_ASSERT(pDocSh);
+ ScDocument& rDoc2 = pDocSh->GetDocument();
+
+ // Get shape
+ ScDrawLayer* pDrawLayer = rDoc2.GetDrawLayer();
+ CPPUNIT_ASSERT_MESSAGE("No ScDrawLayer", pDrawLayer);
+ const SdrPage* pPage = pDrawLayer->GetPage(0);
+ CPPUNIT_ASSERT_MESSAGE("No draw page", pPage);
+ SdrObject* pObj = pPage->GetObj(0);
+ CPPUNIT_ASSERT_MESSAGE("No object found", pObj);
+
+ // Check shape is visible. With the old version, the shape was moved to column C and
+ // thus hidden on reload.
+ CPPUNIT_ASSERT_MESSAGE("Reload: Shape has to be visible", pObj->IsVisible());
+ // Verify position and size are unchanged besides rounding and unit conversion errors
+ // Values are manually taken from shape before hiding column C.
+ const tools::Rectangle aExpectRect(Point(4500, 3500), Size(15143, 5187));
+ const tools::Rectangle aSnapRect = pObj->GetSnapRect();
+ lcl_AssertRectEqualWithTolerance("Reload: wrong pos and size", aExpectRect, aSnapRect, 1);
+
+ pDocSh->DoClose();
+}
+
void ScShapeTest::testTdf137576_LogicRectInDefaultMeasureline()
{
// Error was, that the empty logical rectangle of a default measure line (Ctrl+Click)
@@ -273,8 +464,16 @@ void ScShapeTest::testMeasurelineHideColSave()
lcl_AssertPointEqualWithTolerance("Load start: ", aStartPoint, pObj->GetPoint(0), 1);
lcl_AssertPointEqualWithTolerance("Load end: ", aEndPoint, pObj->GetPoint(1), 1);
- // Hide column A, save and reload
+ // Hide column A
rDoc.SetColHidden(0, 0, 0, true);
+ rDoc.SetDrawPageSize(0); // trigger recalcpos, otherwise shapes are not changed
+ // Shape should move by column width, here 3000
+ aStartPoint.Move(-3000, 0);
+ aEndPoint.Move(-3000, 0);
+ lcl_AssertPointEqualWithTolerance("Hide col A: ", aStartPoint, pObj->GetPoint(0), 1);
+ lcl_AssertPointEqualWithTolerance("Hide col A: ", aEndPoint, pObj->GetPoint(1), 1);
+
+ // save and reload
saveAndReload(xComponent, "calc8");
CPPUNIT_ASSERT(xComponent);
@@ -293,9 +492,9 @@ void ScShapeTest::testMeasurelineHideColSave()
pObj = pPage->GetObj(0);
CPPUNIT_ASSERT_MESSAGE("Reload: custom shape no longer exists", pObj);
- // Check that start and end point are unchanged
- lcl_AssertPointEqualWithTolerance("Reload start: ", aStartPoint, pObj->GetPoint(0), 1);
- lcl_AssertPointEqualWithTolerance("Reload end: ", aEndPoint, pObj->GetPoint(1), 1);
+ // Check that start and end point are unchanged besides rounding and unit conversion errors
+ lcl_AssertPointEqualWithTolerance("Reload start: ", aStartPoint, pObj->GetPoint(0), 2);
+ lcl_AssertPointEqualWithTolerance("Reload end: ", aEndPoint, pObj->GetPoint(1), 2);
pDocSh->DoClose();
}
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index dcaddbca0830..5bc1ff24f0e8 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -114,6 +114,7 @@
#include <svx/unoshape.hxx>
#include <comphelper/base64.hxx>
#include <comphelper/extract.hxx>
+#include <svx/svdoashp.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdocapt.hxx>
#include <vcl/svapp.hxx>
@@ -3475,43 +3476,96 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
if( !(rMyCell.bHasShape && !rMyCell.aShapeList.empty() && pDoc) )
return;
- tools::Rectangle aRectFull = pDoc->GetMMRect(
+ // Reference point
+ tools::Rectangle aCellRectFull = pDoc->GetMMRect(
rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Col(),
rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab(), false /*bHiddenAsZero*/);
- tools::Rectangle aRectReduced = pDoc->GetMMRect(
- rMyCell.maCellAddress.Col(), rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Col(),
- rMyCell.maCellAddress.Row(), rMyCell.maCellAddress.Tab(), true /*bHiddenAsZero*/);
-
- // Reference point
awt::Point aPoint;
bool bNegativePage = pDoc->IsNegativePage(rMyCell.maCellAddress.Tab());
if (bNegativePage)
- aPoint.X = aRectFull.Right();
+ aPoint.X = aCellRectFull.Right();
else
- aPoint.X = aRectFull.Left();
- aPoint.Y = aRectFull.Top();
+ aPoint.X = aCellRectFull.Left();
+ aPoint.Y = aCellRectFull.Top();
+ // ToDo: Adapt the solutions for RTL sheets.
for (const auto& rShape : rMyCell.aShapeList)
{
if (rShape.xShape.is())
{
+ // The current object geometry is based on bHiddenAsZero=true, but ODF file format
+ // needs it as if there were no hidden rows or columns. We manipulate the geometry
+ // accordingly for writing xml markup and restore geometry later.
bool bNeedsRestore = false;
SdrObject* pObj = GetSdrObjectFromXShape(rShape.xShape);
+ // Remember original geometry
SdrObjGeoData* pGeoData = nullptr;
if (pObj)
pGeoData = pObj->GetGeoData();
- if (pObj && aRectFull != aRectReduced)
+ // Hiding row or column affects the shape based on its snap rect. So we need start and
+ // 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 || pObj->GetShearAngle() != 0;
+ }
+ 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.
+ tools::Rectangle aRectFull = pDoc->GetMMRect(
+ aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(),
+ aSnapStartAddress.Row(), aSnapStartAddress.Tab(), false /*bHiddenAsZero*/);
+ tools::Rectangle aRectReduced = pDoc->GetMMRect(
+ aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(),
+ aSnapStartAddress.Row(), aSnapStartAddress.Tab(), true /*bHiddenAsZero*/);
+ const tools::Long nLeftDiff(aRectFull.Left() - aRectReduced.Left());
+ const tools::Long nTopDiff(aRectFull.Top() - aRectReduced.Top());
+ if (pObj && (abs(nLeftDiff) > 1 || abs(nTopDiff) > 1))
{
- // There are hidden rows or columns above or before the start cell.
- // The current object geometry is based on bHiddenAsZero=true, but ODF file format
- // needs it as if there were no hidden rows or columns.
- // We shift the object and restore it later.
bNeedsRestore = true;
- pObj->NbcMove(Size(aRectFull.Left() - aRectReduced.Left(),
- aRectFull.Top() - aRectReduced.Top()));
+ pObj->NbcMove(Size(nLeftDiff, nTopDiff));
+ }
+
+ // 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)
+ {
+ // Get original size from anchor
+ const Point aSnapStartOffset = pObjData->maStartOffset;
+ // In case of 'resize with cell' maEnd and maEndOffset should be valid.
+ const ScAddress aSnapEndAddress(pObjData->maEnd);
+ const Point aSnapEndOffset = pObjData->maEndOffset;
+ const tools::Rectangle aStartCellRect = pDoc->GetMMRect(
+ aSnapStartAddress.Col(), aSnapStartAddress.Row(), aSnapStartAddress.Col(),
+ aSnapStartAddress.Row(), aSnapStartAddress.Tab(), false /*bHiddenAsZero*/);
+ const tools::Rectangle aEndCellRect = pDoc->GetMMRect(
+ aSnapEndAddress.Col(), aSnapEndAddress.Row(), aSnapEndAddress.Col(),
+ aSnapEndAddress.Row(), aSnapEndAddress.Tab(), false /*bHiddenAsZero*/);
+ aRectFull.SetLeft(aStartCellRect.Left() + aSnapStartOffset.X());
+ aRectFull.SetTop(aStartCellRect.Top() + aSnapStartOffset.Y());
+ aRectFull.SetRight(aEndCellRect.Left() + aSnapEndOffset.X());
+ aRectFull.SetBottom(aEndCellRect.Top() + aSnapEndOffset.Y());
+ aRectReduced = pObjData->getShapeRect();
+ if(abs(aRectFull.getWidth() - aRectReduced.getWidth()) > 1
+ || abs(aRectFull.getHeight() - aRectReduced.getHeight()) > 1)
+ {
+ bNeedsRestore = true;
+ Fraction aScaleWidth(aRectFull.getWidth(), aRectReduced.getWidth());
+ if (!aScaleWidth.IsValid())
+ aScaleWidth = Fraction(1.0);
+ Fraction aScaleHeight(aRectFull.getHeight(), aRectReduced.getHeight());
+ if (!aScaleHeight.IsValid())
+ aScaleHeight = Fraction(1.0);
+ pObj->NbcResize(pObj->GetRelativePos(), aScaleWidth, aScaleHeight);
+ }
}
- // ToDo: Adapt object skew and rotation to bHiddenAsZero=false, tdf#137033
// We only write the end address if we want the shape to resize with the cell
if ( rShape.bResizeWithCell &&
@@ -3529,6 +3583,22 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell)
AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear());
}
+ // The general method XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint calculates
+ // offset = translate - refPoint. But in case of a horizontal mirrored, 'resize with cell'
+ // anchored custom shape, translate has wrong values. So we use refPoint = translate
+ // - startOffset which removes translate and sets startOffset directly.
+ // FixMe: Why is translate wrong?
+ if (rShape.bResizeWithCell && pObj && pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE
+ && static_cast<SdrObjCustomShape*>(pObj)->IsMirroredX())
+ {
+ ScDrawObjData* pNRObjData = ScDrawLayer::GetNonRotatedObjData(pObj);
+ if (pNRObjData)
+ {
+ aPoint.X = rShape.xShape->getPosition().X - pNRObjData->maStartOffset.X();
+ aPoint.Y = rShape.xShape->getPosition().Y - pNRObjData->maStartOffset.Y();
+ }
+ }
+
if (bNegativePage)
aPoint.X = 2 * rShape.xShape->getPosition().X + rShape.xShape->getSize().Width
- aPoint.X;