summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzabolcs Toth <toth.szabolcs@nisz.hu>2020-09-16 14:41:24 +0200
committerLászló Németh <nemeth@numbertext.org>2020-09-24 12:54:14 +0200
commit8c23be49fb5a9044989532e6e20feb1e3ff64f2b (patch)
tree9479b0ea74d33dc582d8b9c7266cc3e9281dea74
parent4a899a5f8a72ea29a6919316afe3627de9f33e95 (diff)
tdf#106197 XLSX shape import: keep text upright
Handle and grab-bag attribute upright to keep text upright regardless of shape rotation, fixing the text direction after import and after a round-trip. Co-authored-by: Balázs Regényi Change-Id: If4c73aeaebad55af967cea894a94756068ca3766 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102870 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--oox/inc/drawingml/textbodyproperties.hxx1
-rw-r--r--oox/source/drawingml/shape.cxx24
-rw-r--r--oox/source/drawingml/textbodypropertiescontext.cxx5
-rw-r--r--oox/source/export/drawingml.cxx37
-rw-r--r--sc/qa/unit/data/xlsx/tdf106197_import_upright.xlsxbin0 -> 8919 bytes
-rw-r--r--sc/qa/unit/subsequent_filters-test.cxx45
6 files changed, 89 insertions, 23 deletions
diff --git a/oox/inc/drawingml/textbodyproperties.hxx b/oox/inc/drawingml/textbodyproperties.hxx
index 6e5e97fb94ba..26e34ac6a5f7 100644
--- a/oox/inc/drawingml/textbodyproperties.hxx
+++ b/oox/inc/drawingml/textbodyproperties.hxx
@@ -34,6 +34,7 @@ struct TextBodyProperties
OptValue< sal_Int32 > moRotation;
bool mbAnchorCtr;
OptValue< sal_Int32 > moVert;
+ bool moUpright = false;
std::optional< sal_Int32 > moInsets[4];
std::optional< sal_Int32 > moTextOffUpper;
std::optional< sal_Int32 > moTextOffLeft;
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 02b89312d200..326d90be3ffd 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1409,10 +1409,26 @@ Reference< XShape > const & Shape::createAndInsert(
sal_Int32 nTextRotateAngle = static_cast< sal_Int32 >( getTextBody()->getTextProperties().moRotation.get( 0 ) );
nTextRotateAngle -= mnDiagramRotation;
- /* OOX measures text rotation clockwise in 1/60000th degrees,
- relative to the containing shape. setTextRotateAngle wants
- degrees anticlockwise. */
- mpCustomShapePropertiesPtr->setTextRotateAngle( -1 * nTextRotateAngle / 60000 );
+
+ bool isUpright = getTextBody()->getTextProperties().moUpright;
+ if (isUpright)
+ {
+ // When upright is set, we want the text without any rotation.
+ // But if we set 0 here, the text is still rotated if the
+ // shape containing it is rotated.
+ // Hence, we rotate the text into the 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 Gabbag.
+ putPropertyToGrabBag("Upright", Any(isUpright));
+ }
+ else
+ {
+ /* OOX measures text rotation clockwise in 1/60000th degrees,
+ relative to the containing shape. setTextRotateAngle wants
+ degrees anticlockwise. */
+ mpCustomShapePropertiesPtr->setTextRotateAngle(-1 * nTextRotateAngle / 60000);
+ }
}
// Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks
diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx b/oox/source/drawingml/textbodypropertiescontext.cxx
index b72fa194401a..d3add310097f 100644
--- a/oox/source/drawingml/textbodypropertiescontext.cxx
+++ b/oox/source/drawingml/textbodypropertiescontext.cxx
@@ -94,7 +94,10 @@ TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper cons
// ST_PositiveCoordinate
// sal_Int32 nSpcCol = rAttribs.getInteger( XML_spcCol, 0 );
// bool bSpcFirstLastPara = rAttribs.getBool( XML_spcFirstLastPara, 0 );
-// bool bUpRight = rAttribs.getBool( XML_upright, 0 );
+
+ bool bUpright = rAttribs.getBool(XML_upright, false);
+ if (bUpright)
+ mrTextBodyProp.moUpright = true;
// ST_TextVerticalType
if( rAttribs.hasAttribute( XML_vert ) ) {
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 8d3cbd23a6a7..8ea8035ea39a 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2932,24 +2932,6 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
sVerticalAlignment = "b";
- bool isUpright = false;
- if (GetProperty(rXPropSet, "InteropGrabBag"))
- {
- if (rXPropSet->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
- {
- uno::Sequence<beans::PropertyValue> aGrabBag;
- rXPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
- for (auto& aProp : aGrabBag)
- {
- if (aProp.Name == "Upright")
- {
- aProp.Value >>= isUpright;
- break;
- }
- }
- }
- }
-
bool bHasWrap = false;
bool bWrap = false;
// Only custom shapes obey the TextWordWrap option, normal text always wraps.
@@ -2971,6 +2953,25 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.TextShape"))
pWrap = "square";
}
+
+ bool isUpright = false;
+ if (GetProperty(rXPropSet, "InteropGrabBag"))
+ {
+ if (rXPropSet->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
+ {
+ uno::Sequence<beans::PropertyValue> aGrabBag;
+ rXPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
+ for (auto& aProp : aGrabBag)
+ {
+ if (aProp.Name == "Upright")
+ {
+ aProp.Value >>= isUpright;
+ break;
+ }
+ }
+ }
+ }
+
mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
XML_wrap, pWrap,
XML_fromWordArt, sax_fastparser::UseIf("1", bFromWordArt),
diff --git a/sc/qa/unit/data/xlsx/tdf106197_import_upright.xlsx b/sc/qa/unit/data/xlsx/tdf106197_import_upright.xlsx
new file mode 100644
index 000000000000..5ac0a75eabb6
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tdf106197_import_upright.xlsx
Binary files differ
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 203460654d17..4b8d999dc787 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -279,6 +279,7 @@ public:
void testPreviewMissingObjLink();
void testShapeRotationImport();
void testShapeDisplacementOnRotationImport();
+ void testTextBoxBodyUpright();
CPPUNIT_TEST_SUITE(ScFiltersTest);
CPPUNIT_TEST(testBooleanFormatXLSX);
@@ -448,6 +449,7 @@ public:
CPPUNIT_TEST(testPreviewMissingObjLink);
CPPUNIT_TEST(testShapeRotationImport);
CPPUNIT_TEST(testShapeDisplacementOnRotationImport);
+ CPPUNIT_TEST(testTextBoxBodyUpright);
CPPUNIT_TEST_SUITE_END();
@@ -4910,6 +4912,49 @@ void ScFiltersTest::testShapeDisplacementOnRotationImport()
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRectangle.Y);
}
+void ScFiltersTest::testTextBoxBodyUpright()
+{
+ // tdf#106197 We should import the "upright" attribute of txBody.
+ ScDocShellRef xDocSh = loadDoc("tdf106197_import_upright.", FORMAT_XLSX);
+ CPPUNIT_ASSERT_MESSAGE("Failed to load testTextBoxBodyUpright.xlsx", xDocSh.is());
+
+ uno::Reference<drawing::XDrawPagesSupplier> xDoc(xDocSh->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::XShape> xShape(xPage->getByIndex(0), uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySet> xShapeProperties(xShape, uno::UNO_QUERY_THROW);
+
+ // Check that we imported "Upright".
+ bool isUpright = false;
+ if (xShapeProperties->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
+ {
+ uno::Sequence<beans::PropertyValue> aGrabBag;
+ xShapeProperties->getPropertyValue("InteropGrabBag") >>= aGrabBag;
+ for (auto& aProp : aGrabBag)
+ {
+ if (aProp.Name == "Upright")
+ {
+ aProp.Value >>= isUpright;
+ break;
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(true, isUpright);
+
+ // Check the new textRotateAngle.
+ sal_Int32 nAngle;
+ uno::Any aGeom = xShapeProperties->getPropertyValue("CustomShapeGeometry");
+ auto aGeomSeq = aGeom.get<Sequence<beans::PropertyValue>>();
+ for (const auto& aProp : std::as_const(aGeomSeq))
+ {
+ if (aProp.Name == "TextPreRotateAngle")
+ {
+ aProp.Value >>= nAngle;
+ break;
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(90), nAngle);
+}
+
ScFiltersTest::ScFiltersTest()
: ScBootstrapFixture( "sc/qa/unit/data" )
{