include/oox/drawingml/shape.hxx              |    3 +
 oox/source/drawingml/shape.cxx               |   42 +++++++++++++++++++++++
 oox/source/shape/WpgContext.hxx              |    2 -
 oox/source/shape/WpsContext.cxx              |   43 +++++++++++++++++++++++
 oox/source/shape/WpsContext.hxx              |    1 
 sw/qa/extras/ooxmlexport/data/WPGbodyPr.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx   |   49 +++++++++++++++++++++++++++
 7 files changed, 139 insertions(+), 1 deletion(-)

New commits:
commit 65b09ef1c5e24651579eb11900cf2ddbbb7b0971
Author:     Attila Bakos (NISZ) <bakos.attilakar...@nisz.hu>
AuthorDate: Mon Jan 24 10:57:34 2022 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Feb 3 09:28:52 2022 +0100

    tdf#146803 tdf#146805 OOXML import: fix bodyPr at grouped shapes
    
    Grouped text boxes (WPG) lost their alignment and spacing,
    because the bodyPr tag what has the information for this,
    processed after the textbox content, and applied to the XShape
    which in case of group shape is not ready. To solve this, the
    mentioned properties read for the shape member after copied
    to the XShape when its ready, and than synced to the textbox.
    
    Regression from commit 121cbc250b36290f0f8c7265fea57256dad69553
    "tdf#66039 DOCX: import textboxes (with tables, images etc.) in
    group shapes".
    
    Change-Id: Ifb5e8bde58613137441bec2e2b51bc67118dab40
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128854
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 57a47cbdb4e5..40c8319f67d3 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -205,6 +205,8 @@ public:
     const Color&        getFontRefColorForNodes() const { return 
maFontRefColorForNodes; }
     void                setLockedCanvas(bool bLockedCanvas);
     bool                getLockedCanvas() const { return mbLockedCanvas;}
+    void                setWPGChild(bool bWPG);
+    bool                isWPGChild() const { return mbWPGChild;}
     void                setWps(bool bWps);
     bool                getWps() const { return mbWps;}
     void                setTextBox(bool bTextBox);
@@ -360,6 +362,7 @@ private:
                                                          // we need separate 
flag because we don't want
                                                          // to propagate it 
when applying reference shape
     bool                            mbLocked;
+    bool mbWPGChild; // Is this shape a child of a WPG shape?
     bool mbLockedCanvas; ///< Is this shape part of a locked canvas?
     bool mbWps; ///< Is this a wps shape?
     bool mbTextBox; ///< This shape has a textbox.
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index f7161e01291f..b13000035add 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -134,6 +134,7 @@ Shape::Shape( const char* pServiceName, bool bDefaultHeight 
)
 , mbHidden( false )
 , mbHiddenMasterShape( false )
 , mbLocked( false )
+, mbWPGChild(false)
 , mbLockedCanvas( false )
 , mbWps( false )
 , mbTextBox( false )
@@ -176,6 +177,7 @@ Shape::Shape( const ShapePtr& pSourceShape )
 , mbHidden( pSourceShape->mbHidden )
 , mbHiddenMasterShape( pSourceShape->mbHiddenMasterShape )
 , mbLocked( pSourceShape->mbLocked )
+, mbWPGChild( pSourceShape->mbWPGChild )
 , mbLockedCanvas( pSourceShape->mbLockedCanvas )
 , mbWps( pSourceShape->mbWps )
 , mbTextBox( pSourceShape->mbTextBox )
@@ -292,6 +294,41 @@ void Shape::addShape(
             if ( xShapes.is() )
                 addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, 
aMatrix );
 
+            if (isWPGChild() && xShape)
+            {
+                // This is a wps shape and it is the child of the WPG, now 
copy the
+                // the text body properties to the xshape.
+                Reference<XPropertySet> xChildWPSProperties(xShape, 
uno::UNO_QUERY);
+
+                if (getTextBody() && xChildWPSProperties)
+                {
+                    xChildWPSProperties->setPropertyValue(
+                        UNO_NAME_TEXT_VERTADJUST,
+                        uno::Any(getTextBody()->getTextProperties().meVA));
+
+                    xChildWPSProperties->setPropertyValue(
+                        UNO_NAME_TEXT_LEFTDIST,
+                        
uno::Any(getTextBody()->getTextProperties().moInsets[0].has_value()
+                                     ? 
*getTextBody()->getTextProperties().moInsets[0]
+                                     : 0));
+                    xChildWPSProperties->setPropertyValue(
+                        UNO_NAME_TEXT_UPPERDIST,
+                        
uno::Any(getTextBody()->getTextProperties().moInsets[1].has_value()
+                                     ? 
*getTextBody()->getTextProperties().moInsets[1]
+                                     : 0));
+                    xChildWPSProperties->setPropertyValue(
+                        UNO_NAME_TEXT_RIGHTDIST,
+                        
uno::Any(getTextBody()->getTextProperties().moInsets[2].has_value()
+                                     ? 
*getTextBody()->getTextProperties().moInsets[2]
+                                     : 0));
+                    xChildWPSProperties->setPropertyValue(
+                        UNO_NAME_TEXT_LOWERDIST,
+                        
uno::Any(getTextBody()->getTextProperties().moInsets[3].has_value()
+                                     ? 
*getTextBody()->getTextProperties().moInsets[3]
+                                     : 0));
+                }
+            }
+
             if( meFrameType == FRAMETYPE_DIAGRAM )
             {
                 keepDiagramCompatibilityInfo();
@@ -332,6 +369,11 @@ void Shape::setLockedCanvas(bool bLockedCanvas)
     mbLockedCanvas = bLockedCanvas;
 }
 
+void Shape::setWPGChild(bool bWPG)
+{
+    mbWPGChild = bWPG;
+}
+
 void Shape::setWps(bool bWps)
 {
     mbWps = bWps;
diff --git a/oox/source/shape/WpgContext.hxx b/oox/source/shape/WpgContext.hxx
index 6da13d9663be..414e5f819bfe 100644
--- a/oox/source/shape/WpgContext.hxx
+++ b/oox/source/shape/WpgContext.hxx
@@ -28,7 +28,7 @@ public:
 
     const oox::drawingml::ShapePtr& getShape() const { return mpShape; }
 
-    const bool& isFullWPGSupport() { return m_bFullWPGSupport; };
+    const bool& isFullWPGSupport() const { return m_bFullWPGSupport; };
     void setFullWPGSupport(const bool& rbUse) { m_bFullWPGSupport = rbUse; };
 
 private:
diff --git a/oox/source/shape/WpsContext.cxx b/oox/source/shape/WpsContext.cxx
index 5eaff0abe6e0..d39f93fc8402 100644
--- a/oox/source/shape/WpsContext.cxx
+++ b/oox/source/shape/WpsContext.cxx
@@ -8,6 +8,7 @@
  */
 
 #include "WpsContext.hxx"
+#include "WpgContext.hxx"
 #include <basegfx/matrix/b2dhommatrix.hxx>
 #include <basegfx/tuple/b2dtuple.hxx>
 #include <comphelper/sequenceashashmap.hxx>
@@ -24,6 +25,9 @@
 #include <oox/token/namespaces.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/drawingml/shape.hxx>
+#include <oox/drawingml/drawingmltypes.hxx>
+#include <drawingml/textbody.hxx>
+#include <drawingml/textbodyproperties.hxx>
 
 #include <optional>
 
@@ -39,6 +43,11 @@ WpsContext::WpsContext(ContextHandler2Helper const& rParent, 
uno::Reference<draw
 {
     if (mpShapePtr)
         mpShapePtr->setWps(true);
+
+    if (const auto pParent = dynamic_cast<const WpgContext*>(&rParent))
+        m_bHasWPGParent = pParent->isFullWPGSupport();
+    else
+        m_bHasWPGParent = false;
 }
 
 WpsContext::~WpsContext() = default;
@@ -169,6 +178,40 @@ oox::core::ContextHandlerRef 
WpsContext::onCreateContext(sal_Int32 nElementToken
 
                 return this;
             }
+            else if (m_bHasWPGParent && mpShapePtr)
+            {
+                // this WPS context has to be inside a WPG shape, so the 
<BodyPr> element
+                // cannot be applied to mxShape member, use mpShape instead, 
and after the
+                // the parent shape finished, apply it for its children.
+                mpShapePtr->setWPGChild(true);
+                oox::drawingml::TextBodyPtr pTextBody;
+                pTextBody.reset(new oox::drawingml::TextBody());
+
+                if (rAttribs.hasAttribute(XML_anchor))
+                {
+                    drawing::TextVerticalAdjust eAdjust
+                        = 
drawingml::GetTextVerticalAdjust(rAttribs.getToken(XML_anchor, XML_t));
+                    pTextBody->getTextProperties().meVA = eAdjust;
+                }
+
+                sal_Int32 aInsets[] = { XML_lIns, XML_tIns, XML_rIns, XML_bIns 
};
+                for (int i = 0; i < 4; ++i)
+                {
+                    if (rAttribs.hasAttribute(XML_lIns))
+                    {
+                        OptValue<OUString> oValue = 
rAttribs.getString(aInsets[i]);
+                        if (oValue.has())
+                            pTextBody->getTextProperties().moInsets[i]
+                                = oox::drawingml::GetCoordinate(oValue.get());
+                        else
+                            // Defaults from the spec: left/right: 91440 EMU, 
top/bottom: 45720 EMU
+                            pTextBody->getTextProperties().moInsets[i]
+                                = (aInsets[i] == XML_lIns || aInsets[i] == 
XML_rIns) ? 254 : 127;
+                    }
+                }
+
+                mpShapePtr->setTextBody(pTextBody);
+            }
             break;
         case XML_noAutofit:
         case XML_spAutoFit:
diff --git a/oox/source/shape/WpsContext.hxx b/oox/source/shape/WpsContext.hxx
index 1cb6106324da..29110b6fbf8e 100644
--- a/oox/source/shape/WpsContext.hxx
+++ b/oox/source/shape/WpsContext.hxx
@@ -36,6 +36,7 @@ public:
 
 private:
     css::uno::Reference<css::drawing::XShape> mxShape;
+    bool m_bHasWPGParent;
 };
 }
 
diff --git a/sw/qa/extras/ooxmlexport/data/WPGbodyPr.docx 
b/sw/qa/extras/ooxmlexport/data/WPGbodyPr.docx
new file mode 100644
index 000000000000..a0a9ae764ba2
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/WPGbodyPr.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index ee7b37dfc151..10e5aab2129c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -12,6 +12,7 @@
 
 #include <comphelper/scopeguard.hxx>
 #include <officecfg/Office/Common.hxx>
+#include <com/sun/star/drawing/XShapes.hpp>
 
 #include <queue>
 #include <swmodeltestbase.hxx>
@@ -193,6 +194,54 @@ DECLARE_OOXMLEXPORT_TEST(testTdf142407, "tdf142407.docx")
     CPPUNIT_ASSERT_EQUAL( sal_Int16(36), nGridLines);   // was 23, left large 
space before text.
 }
 
+DECLARE_OOXMLEXPORT_TEST(testWPGBodyPr, "WPGbodyPr.docx")
+{
+    // Is load successful?
+    CPPUNIT_ASSERT(mxComponent);
+
+    // There are a WPG shape and a picture
+    CPPUNIT_ASSERT_EQUAL(2, getShapes());
+
+    // Get the WPG shape
+    uno::Reference<drawing::XShapes> xGroup(getShape(2), uno::UNO_QUERY);
+    // And the embed WPG
+    uno::Reference<drawing::XShapes> xEmbedGroup(xGroup->getByIndex(1), 
uno::UNO_QUERY);
+
+    // Get the properties of the shapes
+    uno::Reference<beans::XPropertySet> xOuterShape(xGroup->getByIndex(0), 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> 
xMiddleShape(xEmbedGroup->getByIndex(0), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> 
xInnerShape(xEmbedGroup->getByIndex(1), uno::UNO_QUERY);
+
+    // Get the properties of the textboxes too
+    uno::Reference<beans::XPropertySet> xOuterTextBox(
+        xOuterShape->getPropertyValue("TextBoxContent"), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xMiddleTextBox(
+        xMiddleShape->getPropertyValue("TextBoxContent"), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xInnerTextBox(
+        xInnerShape->getPropertyValue("TextBoxContent"), uno::UNO_QUERY);
+
+    // Check the alignments
+    
CPPUNIT_ASSERT_EQUAL(css::drawing::TextVerticalAdjust::TextVerticalAdjust_TOP,
+                         xOuterTextBox->getPropertyValue("TextVerticalAdjust")
+                             .get<css::drawing::TextVerticalAdjust>());
+    
CPPUNIT_ASSERT_EQUAL(css::drawing::TextVerticalAdjust::TextVerticalAdjust_TOP,
+                         xMiddleTextBox->getPropertyValue("TextVerticalAdjust")
+                             .get<css::drawing::TextVerticalAdjust>());
+    
CPPUNIT_ASSERT_EQUAL(css::drawing::TextVerticalAdjust::TextVerticalAdjust_CENTER,
+                         xInnerTextBox->getPropertyValue("TextVerticalAdjust")
+                             .get<css::drawing::TextVerticalAdjust>());
+
+    // Check the inset margins, all were 0 before the fix
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(499),
+                         
xInnerShape->getPropertyValue("TextLowerDistance").get<sal_Int32>());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(499),
+                         
xInnerShape->getPropertyValue("TextUpperDistance").get<sal_Int32>());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1000),
+                         
xInnerShape->getPropertyValue("TextLeftDistance").get<sal_Int32>());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(254),
+                         
xInnerShape->getPropertyValue("TextRightDistance").get<sal_Int32>());
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf81507, "tdf81507.docx")
 {
     xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");

Reply via email to