[Libreoffice-commits] core.git: include/oox oox/qa oox/source sw/inc sw/qa sw/source

Regényi Balázs (via logerrit) logerrit at kemper.freedesktop.org
Thu Dec 10 09:28:16 UTC 2020


 include/oox/export/drawingml.hxx                                    |    4 
 include/oox/vml/vmlshape.hxx                                        |   10 ++
 oox/qa/unit/vml.cxx                                                 |   19 ---
 oox/source/export/drawingml.cxx                                     |   34 ++++++
 oox/source/export/vmlexport.cxx                                     |   50 ++++++++--
 oox/source/vml/vmlshape.cxx                                         |   32 ++++++
 oox/source/vml/vmlshapecontext.cxx                                  |   20 ++--
 sw/inc/textboxhelper.hxx                                            |    7 +
 sw/qa/extras/ooxmlexport/data/tdf41466_testVmlShapeWithTextbox.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx                           |   24 ++++
 sw/source/core/doc/textboxhelper.cxx                                |   23 ++++
 sw/source/core/unocore/unodraw.cxx                                  |    9 +
 sw/source/filter/ww8/docxattributeoutput.cxx                        |    6 +
 sw/source/filter/ww8/docxattributeoutput.hxx                        |    2 
 14 files changed, 207 insertions(+), 33 deletions(-)

New commits:
commit bda05ba17362222b74727872579b65b3fa14e3d8
Author:     Regényi Balázs <regenyi.balazs at nisz.hu>
AuthorDate: Tue Dec 1 12:16:12 2020 +0100
Commit:     László Németh <nemeth at numbertext.org>
CommitDate: Thu Dec 10 10:27:33 2020 +0100

    tdf#41466 DOCX import: fix VML v:shape/v:textbox
    
    VML v:shape/v:textbox element was imported only as
    a text frame, losing (otherwise recognized) preset
    shape geometry, i.e. replacing a callout bubble
    (wedgeRectCallout) and other special shapes with a
    plain rectangle.
    
    Thanks to Attila Bakos for the initial help.
    
    Change-Id: I03a608822ed54a20ed07406a08c3539e72958f5b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105299
    Tested-by: Jenkins
    Reviewed-by: László Németh <nemeth at numbertext.org>

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 31eeb727760f..9f87e54c1361 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -70,6 +70,7 @@ namespace style {
 namespace text {
     class XTextContent;
     class XTextRange;
+    class XTextFrame;
 }
 namespace io {
     class XOutputStream;
@@ -125,6 +126,9 @@ public:
     virtual OUString FindRelId(BitmapChecksum nChecksum) = 0;
     /// Store the RelId of a graphic based on its checksum.
     virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) = 0;
+    ///  Get textbox which belongs to the shape.
+    virtual css::uno::Reference<css::text::XTextFrame> GetUnoTextFrame(
+        css::uno::Reference<css::drawing::XShape> xShape) = 0;
 protected:
     DMLTextExport() {}
     virtual ~DMLTextExport() {}
diff --git a/include/oox/vml/vmlshape.hxx b/include/oox/vml/vmlshape.hxx
index 7703b311c757..0e50e5b6ee1f 100644
--- a/include/oox/vml/vmlshape.hxx
+++ b/include/oox/vml/vmlshape.hxx
@@ -216,6 +216,7 @@ struct ShapeModel
     OUString     maSignatureLineSigningInstructions;
     bool         mbSignatureLineShowSignDate;
     bool         mbSignatureLineCanAddComment;
+    bool         mbInGroup;
 
     explicit            ShapeModel();
                         ~ShapeModel();
@@ -275,6 +276,13 @@ protected:
                             const css::uno::Reference< css::drawing::XShapes >& rxShapes,
                             const css::awt::Rectangle& rShapeRect ) const = 0;
 
+    /** Always called after implConvertAndInsert for the same task.*/
+    virtual css::uno::Reference<css::drawing::XShape> finalImplConvertAndInsert(
+        const css::uno::Reference<css::drawing::XShape>& rxShape) const
+    {
+        return rxShape;
+    };
+
     /** Calculates the final shape rectangle according to the passed anchor,
         if present, otherwise according to the own anchor settings. */
     css::awt::Rectangle calcShapeRectangle(
@@ -304,6 +312,8 @@ protected:
                         implConvertAndInsert(
                             const css::uno::Reference< css::drawing::XShapes >& rxShapes,
                             const css::awt::Rectangle& rShapeRect ) const override;
+    virtual css::uno::Reference<css::drawing::XShape> finalImplConvertAndInsert(
+        const css::uno::Reference<css::drawing::XShape>& rxShape) const override;
     /** Used by both RectangleShape and ComplexShape. */
     css::uno::Reference<css::drawing::XShape>createEmbeddedPictureObject(
         const css::uno::Reference< css::drawing::XShapes >& rxShapes,
diff --git a/oox/qa/unit/vml.cxx b/oox/qa/unit/vml.cxx
index d43d2d5645ae..ec64a08c3fcf 100644
--- a/oox/qa/unit/vml.cxx
+++ b/oox/qa/unit/vml.cxx
@@ -55,25 +55,6 @@ void OoxVmlTest::load(const OUString& rFileName)
     mxComponent = loadFromDesktop(aURL);
 }
 
-CPPUNIT_TEST_FIXTURE(OoxVmlTest, testLayoutFlowAltAlone)
-{
-    // mso-layout-flow-alt:bottom-to-top without a matching layout-flow:vertical.
-    load("layout-flow-alt-alone.docx");
-
-    uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY);
-    uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
-                                                 uno::UNO_QUERY);
-    uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
-    sal_Int16 nWritingMode = 0;
-    xShape->getPropertyValue("WritingMode") >>= nWritingMode;
-
-    // Without the accompanying fix in place, this test would have failed with:
-    // - Expected: 5 [ BTLR ]
-    // - Actual  : 4 [ PAGE ]
-    // i.e. in case layout-flow:vertical was missing, the text was not vertical.
-    CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, nWritingMode);
-}
-
 CPPUNIT_TEST_FIXTURE(OoxVmlTest, testSpt202ShapeType)
 {
     // Load a document with a groupshape, 2nd child is a <v:shape>, its type has o:spt set to 202
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index f309e1541409..5374812fa094 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -88,6 +88,7 @@
 #include <com/sun/star/text/XTextContent.hpp>
 #include <com/sun/star/text/XTextField.hpp>
 #include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/style/CaseMap.hpp>
 #include <com/sun/star/xml/dom/XNodeList.hpp>
 #include <com/sun/star/xml/sax/Writer.hpp>
@@ -2942,6 +2943,39 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
             }
         }
     }
+    else
+    {
+        if (mpTextExport)
+        {
+            uno::Reference<drawing::XShape> xShape(rXIface, uno::UNO_QUERY);
+            if (xShape)
+            {
+                auto xTextFrame = mpTextExport->GetUnoTextFrame(xShape);
+                if (xTextFrame)
+                {
+                    uno::Reference<beans::XPropertySet> xPropSet(xTextFrame, uno::UNO_QUERY);
+                    auto aAny = xPropSet->getPropertyValue("WritingMode");
+                    sal_Int16 nWritingMode;
+                    if (aAny >>= nWritingMode)
+                    {
+                        switch (nWritingMode)
+                        {
+                        case WritingMode2::TB_RL:
+                            sWritingMode = "vert";
+                            bVertical = true;
+                            break;
+                        case WritingMode2::BT_LR:
+                            sWritingMode = "vert270";
+                            bVertical = true;
+                            break;
+                        default:
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
     OUString sPresetWarp(PresetGeometryTypeNames::GetMsoName(sShapeType));
     // ODF may have user defined TextPath, use "textPlain" as ersatz.
     if (sPresetWarp.isEmpty())
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 430ade878bf2..5ef5ed096b2e 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -46,6 +46,8 @@
 #include <com/sun/star/text/HoriOrientation.hpp>
 #include <com/sun/star/text/VertOrientation.hpp>
 #include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
 
 #include <cstdio>
 
@@ -1470,15 +1472,49 @@ void VMLExport::EndShape( sal_Int32 nShapeElement )
 
     if (m_pTextExport && lcl_isTextBox(m_pSdrObject))
     {
-        uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
-        comphelper::SequenceAsHashMap aCustomShapeProperties(xPropertySet->getPropertyValue("CustomShapeGeometry"));
-        sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
-        if (aCustomShapeProperties.find("TextPreRotateAngle") != aCustomShapeProperties.end())
+        uno::Reference<drawing::XShape> xShape {const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY};
+        uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
+        bool bBottomToTop = false;
+        if (xPropertySetInfo->hasPropertyByName("CustomShapeGeometry"))
         {
-            sal_Int32 nTextRotateAngle = aCustomShapeProperties["TextPreRotateAngle"].get<sal_Int32>();
-            if (nTextRotateAngle == -270)
-                pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
+            // In this case a DrawingML DOCX was imported.
+            comphelper::SequenceAsHashMap aCustomShapeProperties(
+                xPropertySet->getPropertyValue("CustomShapeGeometry"));
+            if (aCustomShapeProperties.find("TextPreRotateAngle") != aCustomShapeProperties.end())
+            {
+                sal_Int32 nTextRotateAngle = aCustomShapeProperties["TextPreRotateAngle"].get<sal_Int32>();
+                if (nTextRotateAngle == -270)
+                    bBottomToTop = true;
+            }
         }
+        else
+        {
+            // In this case a pure VML DOCX was imported, so there is no CustomShapeGeometry.
+            auto pTextExport = m_pTextExport->GetDrawingML().GetTextExport();
+            // FIXME: somewhy pTextExport is always nullptr, we should find its reason
+            if (pTextExport)
+            {
+                auto xTextFrame = pTextExport->GetUnoTextFrame(xShape);
+                uno::Reference<beans::XPropertySet> xPropSet(xTextFrame, uno::UNO_QUERY);
+                auto aAny = xPropSet->getPropertyValue("WritingMode");
+                sal_Int16 nWritingMode;
+                if (aAny >>= nWritingMode)
+                {
+                    switch (nWritingMode)
+                    {
+                        case text::WritingMode2::BT_LR:
+                            bBottomToTop = true;
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+        sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
+        if (bBottomToTop)
+            pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
         sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
         pTextboxAttrList = nullptr;
         m_pSerializer->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx
index 1e3e1f72e64d..7ee10203341e 100644
--- a/oox/source/vml/vmlshape.cxx
+++ b/oox/source/vml/vmlshape.cxx
@@ -69,6 +69,7 @@
 #include <comphelper/processfactory.hxx>
 #include <comphelper/propertyvalue.hxx>
 #include <comphelper/storagehelper.hxx>
+#include <comphelper/sequenceashashmap.hxx>
 
 using ::com::sun::star::beans::XPropertySet;
 using ::com::sun::star::uno::Any;
@@ -259,6 +260,7 @@ ShapeModel::ShapeModel()
     : mbIsSignatureLine(false)
     , mbSignatureLineShowSignDate(true)
     , mbSignatureLineCanAddComment(false)
+    , mbInGroup(false)
 {
 }
 
@@ -459,6 +461,8 @@ Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxS
                     PropertySet aControlShapeProp( xControlShape->getControl() );
                     aControlShapeProp.setProperty( PROP_EnableVisible, uno::makeAny( false ) );
                 }
+
+                xShape = finalImplConvertAndInsert(xShape);
                 /*  Notify the drawing that a new shape has been inserted. For
                     convenience, pass the rectangle that contains position and
                     size of the shape. */
@@ -887,6 +891,34 @@ Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes
     return xShape;
 }
 
+Reference<XShape> SimpleShape::finalImplConvertAndInsert(const css::uno::Reference<css::drawing::XShape>& rxShape) const
+{
+    // tdf#41466 This setting must be done here, because the position of textbox will be set as an
+    // effect of the PROP_TextBox property setting, and if we do this setting earlier (setting of
+    // properties of position and size) then the position of textbox will be set with wrong data.
+    // TODO: TextShape is set if we have rect shape in group; we should use the shape-with-textbox
+    // mechanism to handle this situation
+    if (getTextBox() && maService != "com.sun.star.text.TextFrame" && maService != "com.sun.star.drawing.TextShape"
+        && !maShapeModel.mbInGroup)
+    {
+        const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
+        const auto& nLeft = ConversionHelper::decodeMeasureToHmm(
+            rGraphicHelper, maTypeModel.maMarginLeft, 0, true, true);
+        PropertySet aPropertySet(rxShape);
+        aPropertySet.setProperty(PROP_HoriOrientPosition, nLeft);
+        const auto& nTop = ConversionHelper::decodeMeasureToHmm(
+            rGraphicHelper, maTypeModel.maMarginTop, 0, true, true);
+        aPropertySet.setProperty(PROP_VertOrientPosition, nTop);
+        aPropertySet.setProperty(PROP_TextBox, true);
+
+        // And these properties must be set after textbox creation (set PROP_Textbox property).
+        // Note: if you set a new property then you have to handle it in the proper
+        // SwTextBoxHelper::syncProperty function.
+        if (maTypeModel.maLayoutFlowAlt == "bottom-to-top")
+            aPropertySet.setAnyProperty(PROP_TextWritingMode, uno::makeAny(text::WritingMode2::BT_LR));
+    }
+    return ShapeBase::finalImplConvertAndInsert(rxShape);
+}
 Reference< XShape > SimpleShape::createEmbeddedPictureObject( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect, OUString const & rGraphicPath ) const
 {
     Reference<XGraphic> xGraphic = mrDrawing.getFilter().getGraphicHelper().importEmbeddedGraphic(rGraphicPath);
diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx
index f1ba9e32340c..e8f1b0b1910e 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -499,20 +499,26 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const Attri
                     nShapeType = pShapeType->getTypeModel().moShapeType.get();
                 }
             }
+            mrShapeModel.mbInGroup = (getParentElement() == VML_TOKEN(group));
 
-            if (getParentElement() != VML_TOKEN( group ))
+            // FIXME: the shape with textbox should be used for the next cases
+            if (getCurrentElement() == VML_TOKEN(rect) || nShapeType == ESCHER_ShpInst_TextBox)
             {
-                // Custom shape in Writer with a textbox are transformed into a frame
-                dynamic_cast<SimpleShape&>( mrShape ).setService(
-                        "com.sun.star.text.TextFrame");
+                if (mrShapeModel.mbInGroup)
+                    // FIXME: without this a text will be added into the group-shape instead of its
+                    // parent shape
+                    dynamic_cast<SimpleShape&>(mrShape).setService("com.sun.star.drawing.TextShape");
+                else
+                    // FIXME: without this we does not handle some properties like shadow
+                    dynamic_cast<SimpleShape&>(mrShape).setService("com.sun.star.text.TextFrame");
             }
-            else if (getCurrentElement() == VML_TOKEN(rect) || nShapeType == ESCHER_ShpInst_TextBox)
-                // Transform only rectangles into a TextShape inside a groupshape.
-                dynamic_cast<SimpleShape&>(mrShape).setService("com.sun.star.drawing.TextShape");
             return new TextBoxContext( *this, mrShapeModel.createTextBox(mrShape.getTypeModel()), rAttribs,
                 mrShape.getDrawing().getFilter().getGraphicHelper());
         }
         case VMLX_TOKEN( ClientData ):
+            // tdf#41466 ActiveX control shapes with a textbox are transformed into a frame
+            // (see unit test testActiveXOptionButtonGroup)
+            dynamic_cast<SimpleShape&>(mrShape).setService("com.sun.star.text.TextFrame");
             return new ClientDataContext( *this, mrShapeModel.createClientData(), rAttribs );
         case VMLPPT_TOKEN( textdata ):
             // Force RectangleShape, this is ugly :(
diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index a0cd4c593082..6d209d2c7140 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -35,6 +35,10 @@ namespace com::sun::star::drawing
 {
 class XShape;
 }
+namespace com::sun::star::text
+{
+class XTextFrame;
+}
 
 /**
  * A TextBox is a TextFrame, that is tied to a drawinglayer shape.
@@ -85,6 +89,9 @@ public:
     /// If we have an associated TextFrame, then return that.
     static SwFrameFormat*
     getOtherTextBoxFormat(css::uno::Reference<css::drawing::XShape> const& xShape);
+    /// If we have an associated TextFrame, then return its XTextFrame.
+    static css::uno::Reference<css::text::XTextFrame>
+    getUnoTextFrame(css::uno::Reference<css::drawing::XShape> const& xShape);
     /// Return the textbox rectangle of a draw shape (in twips).
     static tools::Rectangle getTextRectangle(SwFrameFormat* pShape, bool bAbsolute = true);
 
diff --git a/oox/qa/unit/data/layout-flow-alt-alone.docx b/sw/qa/extras/ooxmlexport/data/layout-flow-alt-alone.docx
similarity index 100%
rename from oox/qa/unit/data/layout-flow-alt-alone.docx
rename to sw/qa/extras/ooxmlexport/data/layout-flow-alt-alone.docx
diff --git a/sw/qa/extras/ooxmlexport/data/tdf41466_testVmlShapeWithTextbox.docx b/sw/qa/extras/ooxmlexport/data/tdf41466_testVmlShapeWithTextbox.docx
new file mode 100644
index 000000000000..2dfeb909cf9d
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf41466_testVmlShapeWithTextbox.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index 251bc2dcb952..47ee7a99b351 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -1622,6 +1622,30 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testAlignmentRelativeFromTopMarginVML, "tdf1
                        "center");
 }
 
+DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testVmlShapeWithTextbox, "tdf41466_testVmlShapeWithTextbox.docx")
+{
+    // Import as VML.
+    // tdf#41466: check whether VML DOCX shape with text is imported as shape with a text frame
+    // (text box). These kind of shapes were imported only as text frames previously, losing the
+    // preset shape geometry, in this case "wedgeRectCallout".
+    xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
+
+    // the wrong value was "rect" instead of "wedgeRectCallout"
+    assertXPath(pXmlDoc,
+        "/w:document/w:body/w:p/w:r/"
+        "mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+        "prst", "wedgeRectCallout");
+}
+
+DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testLayoutFlowAltAlone, "layout-flow-alt-alone.docx")
+{
+    // moved from oox/qa/unit/vml.cxx
+    // FIXME: now the DML part is checked, but we should check VML part in Fallback (too)
+    xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/"
+        "a:graphic/a:graphicData/wps:wsp/wps:bodyPr", "vert", "vert270");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 0d66639baf83..f569cb4ff595 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -44,6 +44,7 @@
 #include <com/sun/star/text/TextContentAnchorType.hpp>
 #include <com/sun/star/text/WrapTextMode.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/table/BorderLine2.hpp>
 #include <com/sun/star/text/WritingMode.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
@@ -357,6 +358,25 @@ SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XS
     return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT);
 }
 
+uno::Reference<text::XTextFrame>
+SwTextBoxHelper::getUnoTextFrame(uno::Reference<drawing::XShape> const& xShape)
+{
+    if (xShape)
+    {
+        auto pFrameFormat = SwTextBoxHelper::getOtherTextBoxFormat(xShape);
+        if (pFrameFormat)
+        {
+            auto pSdrObj = pFrameFormat->FindSdrObject();
+            if (pSdrObj && pSdrObj->IsTextBox())
+            {
+                return uno::Reference<css::text::XTextFrame>(pSdrObj->getUnoShape(),
+                                                             uno::UNO_QUERY);
+            }
+        }
+    }
+    return uno::Reference<css::text::XTextFrame>();
+}
+
 template <typename T> static void lcl_queryInterface(const SwFrameFormat* pShape, uno::Any& rAny)
 {
     if (SwFrameFormat* pFormat = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
@@ -537,8 +557,11 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, std::u16string_view rP
     else if (rPropertyName == UNO_NAME_TEXT_WRITINGMODE)
     {
         text::WritingMode eMode;
+        sal_Int16 eMode2;
         if (rValue >>= eMode)
             syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)));
+        else if (rValue >>= eMode2)
+            syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(eMode2));
     }
 }
 
diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx
index fa2fdfb24944..087949787d89 100644
--- a/sw/source/core/unocore/unodraw.cxx
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -737,6 +737,15 @@ void SwXDrawPage::remove(const uno::Reference< drawing::XShape > & xShape)
     SolarMutexGuard aGuard;
     if(!m_pDoc)
         throw uno::RuntimeException();
+    // tdf#41466 remove TextFrame too which is belonged to the actual shape
+    auto xTextFrame = SwTextBoxHelper::getUnoTextFrame(xShape);
+    if (xTextFrame)
+    {
+        uno::Reference<lang::XComponent> xComp(xTextFrame, uno::UNO_QUERY);
+        if (xComp)
+            xComp->dispose();
+    }
+    // remove shape
     uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
     xComp->dispose();
 }
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 5b246d999254..bf25b3111379 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -4904,6 +4904,12 @@ void DocxAttributeOutput::CacheRelId(BitmapChecksum nChecksum, const OUString& r
         m_aSdrRelIdCache.top()[nChecksum] = rRelId;
 }
 
+uno::Reference<css::text::XTextFrame> DocxAttributeOutput::GetUnoTextFrame(
+    css::uno::Reference<css::drawing::XShape> xShape)
+{
+    return SwTextBoxHelper::getUnoTextFrame(xShape);
+}
+
 OString DocxAttributeOutput::getExistingGraphicRelId(BitmapChecksum nChecksum)
 {
     OString aResult;
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index b9278e7f771c..349cab0cb310 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1025,6 +1025,8 @@ public:
     virtual void WriteTextBox(css::uno::Reference<css::drawing::XShape> xShape) override;
     virtual OUString FindRelId(BitmapChecksum nChecksum) override;
     virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) override;
+    virtual css::uno::Reference<css::text::XTextFrame> GetUnoTextFrame(
+        css::uno::Reference<css::drawing::XShape> xShape) override;
     virtual oox::drawingml::DrawingML& GetDrawingML() override;
     virtual void MaybeOutputBrushItem(SfxItemSet const&) override;
 


More information about the Libreoffice-commits mailing list