summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzabolcs Toth <toth.szabolcs@nisz.hu>2020-09-17 11:22:09 +0200
committerLászló Németh <nemeth@numbertext.org>2020-10-06 09:45:51 +0200
commitff5ca4e5fc6a9fb24b0eb6eb629210b024473f67 (patch)
treeb8855d7478fea1aaee4d3a61aacd6695a68a1e45
parentdfa1856cdb4c69985ef1e809d33055427b6fbd76 (diff)
tdf#137000 XLSX shape export: fix upright
Upright is an XML attribute of xdr:txBody/a:bodyPr. It is set in MSO when in a textbox menu we choose "Do not rotate this element". LO import uses a text rotation opposite shape rotation to create upright text, but when exporting the attribute "upright" we must make sure that the text rotation in bodyPr is 0, not the temporary opposite value. Otherwise MSO rotates the text. Note: integer precision of rotation is enough for interoperability, because it's possible to rotate the shapes only by whole degrees in MSO. Follow-up of commit 8c23be49fb5a9044989532e6e20feb1e3ff64f2b (tdf#106197 XLSX shape import: keep text upright). Co-authored-by: Balázs Regényi Change-Id: I0ffae41f83d3fc3a1fa37f413a8fc9fd8ccd9b6b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103094 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--oox/source/drawingml/shape.cxx9
-rw-r--r--oox/source/export/drawingml.cxx37
-rw-r--r--sc/qa/unit/data/xlsx/tdf137000_export_upright.xlsxbin0 -> 8919 bytes
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx22
4 files changed, 61 insertions, 7 deletions
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index f8f65d09f59f..c9ade16f7a1d 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1410,8 +1410,7 @@ Reference< XShape > const & Shape::createAndInsert(
nTextRotateAngle -= mnDiagramRotation;
- bool isUpright = getTextBody()->getTextProperties().moUpright;
- if (isUpright)
+ if (getTextBody()->getTextProperties().moUpright)
{
// When upright is set, we want the text without any rotation.
// But if we set 0 here, the text is still rotated if the
@@ -1419,8 +1418,10 @@ Reference< XShape > const & Shape::createAndInsert(
// Hence, we rotate the text into the opposite direction of
// the rotation of the shape, by as much as the shape was rotated.
mpCustomShapePropertiesPtr->setTextRotateAngle(mnRotation / 60000);
- // Also put this away in a GrabBag.
- putPropertyToGrabBag("Upright", Any(isUpright));
+ // Also put the initial angles away in a GrabBag.
+ putPropertyToGrabBag("Upright", Any(true));
+ putPropertyToGrabBag("nShapeRotationAtImport", Any(mnRotation / 60000));
+ putPropertyToGrabBag("nTextRotationAtImport", Any(mnRotation / 60000));
}
else
{
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 01f926c0c90c..4a9ac9f69014 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2954,20 +2954,31 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
pWrap = "square";
}
- bool isUpright = false;
std::optional<OUString> sHorzOverflow;
std::optional<OUString> sVertOverflow;
+ sal_Int32 nShapeRotateAngle = 0;
+ if (GetProperty(rXPropSet, "RotateAngle"))
+ nShapeRotateAngle = rXPropSet->getPropertyValue("RotateAngle").get<sal_Int32>() / 300;
+ Reference< XPropertySet > xTextSet(xXText, UNO_QUERY);
+ sal_Int32 nShapeTextRotateAngle = 0;
+ if (GetProperty(xTextSet, "RotateAngle"))
+ nShapeTextRotateAngle = rXPropSet->getPropertyValue("RotateAngle").get<sal_Int32>() / 300;
+ std::optional<OString> isUpright;
if (GetProperty(rXPropSet, "InteropGrabBag"))
{
if (rXPropSet->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
{
+ bool bUpright = false;
+ sal_Int32 nOldShapeRotation = 0;
+ sal_Int32 nOldTextRotation = 0;
uno::Sequence<beans::PropertyValue> aGrabBag;
rXPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
for (const auto& aProp : std::as_const(aGrabBag))
{
if (aProp.Name == "Upright")
{
- aProp.Value >>= isUpright;
+ aProp.Value >>= bUpright;
+ isUpright = OString(bUpright ? "1" : "0");
}
else if (aProp.Name == "horzOverflow")
{
@@ -2982,6 +2993,26 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
sVertOverflow = sValue;
}
}
+ if (bUpright)
+ {
+ for (auto& aProp : aGrabBag)
+ {
+ if (aProp.Name == "nShapeRotationAtImport")
+ aProp.Value >>= nOldShapeRotation;
+ else if (aProp.Name == "nTextRotationAtImport")
+ aProp.Value >>= nOldTextRotation;
+ }
+ // So our shape with the textbox in it was not rotated.
+ // Keep upright and make the preRotateAngle 0, it is an attribute
+ // of textBodyPr and must be 0 when upright is true, otherwise
+ // bad rotation happens in MSO.
+ if (nShapeRotateAngle == nOldShapeRotation && nShapeTextRotateAngle == nOldTextRotation)
+ nTextPreRotateAngle = 0;
+ // So we rotated the shape, in this case lose upright and do
+ // as LO normally does.
+ else
+ isUpright.reset();
+ }
}
}
@@ -2997,7 +3028,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
XML_anchor, sVerticalAlignment,
XML_anchorCtr, sax_fastparser::UseIf("1", bHorizontalCenter),
XML_vert, sWritingMode,
- XML_upright, isUpright ? "1" : "0",
+ XML_upright, isUpright,
XML_rot, sax_fastparser::UseIf(oox::drawingml::calcRotationValue((nTextPreRotateAngle + nTextRotateAngle) * 100), (nTextPreRotateAngle + nTextRotateAngle) != 0));
if (bIsFontworkShape)
{
diff --git a/sc/qa/unit/data/xlsx/tdf137000_export_upright.xlsx b/sc/qa/unit/data/xlsx/tdf137000_export_upright.xlsx
new file mode 100644
index 000000000000..5ac0a75eabb6
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tdf137000_export_upright.xlsx
Binary files differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index a5e935dfb740..89a3659fe640 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -270,6 +270,8 @@ public:
void testTdf123353();
void testTdf133688_precedents();
void testTdf91251_missingOverflowRoundtrip();
+ void testTdf137000_handle_upright();
+
CPPUNIT_TEST_SUITE(ScExportTest);
CPPUNIT_TEST(test);
@@ -434,6 +436,7 @@ public:
CPPUNIT_TEST(testTdf123353);
CPPUNIT_TEST(testTdf133688_precedents);
CPPUNIT_TEST(testTdf91251_missingOverflowRoundtrip);
+ CPPUNIT_TEST(testTdf137000_handle_upright);
CPPUNIT_TEST_SUITE_END();
@@ -5483,6 +5486,25 @@ void ScExportTest::testTdf91251_missingOverflowRoundtrip()
assertXPath(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr", "horzOverflow", "clip");
}
+void ScExportTest::testTdf137000_handle_upright()
+{
+ // tdf#106197 When exporting the "upright" attribute, we must set
+ // TextPreRotateAngle to 0.
+ // (Upright is an xml attribute of xdr:txBody/a:bodyPr. It is set when
+ // in a textbox menu we choose: do not rotate this element.)
+ ScDocShellRef xShell = loadDoc("tdf137000_export_upright.", FORMAT_XLSX);
+ CPPUNIT_ASSERT(xShell.is());
+
+ std::shared_ptr<utl::TempFile> pXPathFile
+ = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_XLSX);
+ xmlDocUniquePtr pDrawing
+ = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml");
+ CPPUNIT_ASSERT(pDrawing);
+
+ assertXPathNoAttribute(pDrawing, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr",
+ "rot");
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
CPPUNIT_PLUGIN_IMPLEMENT();