diff options
-rw-r--r-- | oox/inc/drawingml/textbodyproperties.hxx | 1 | ||||
-rw-r--r-- | oox/source/drawingml/shape.cxx | 24 | ||||
-rw-r--r-- | oox/source/drawingml/textbodypropertiescontext.cxx | 5 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 37 | ||||
-rw-r--r-- | sc/qa/unit/data/xlsx/tdf106197_import_upright.xlsx | bin | 0 -> 8919 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_filters-test.cxx | 45 |
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 Binary files differnew file mode 100644 index 000000000000..5ac0a75eabb6 --- /dev/null +++ b/sc/qa/unit/data/xlsx/tdf106197_import_upright.xlsx 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" ) { |