sw/qa/extras/ooxmlexport/data/tdf167770_marginInsideOutside.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport22.cxx                       |   61 
++++++++
 sw/source/filter/ww8/docxsdrexport.cxx                           |    4 
 sw/source/writerfilter/dmapper/GraphicImport.cxx                 |   70 
++++++----
 4 files changed, 106 insertions(+), 29 deletions(-)

New commits:
commit 188fc004c3e1448ed68b6e1a96932886da04bc82
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Sat Aug 2 10:59:56 2025 -0400
Commit:     Justin Luth <justin.l...@collabora.com>
CommitDate: Mon Aug 4 17:19:29 2025 +0200

    related tdf#167770 docx import/export: support INSIDE/OUTSIDE
    
    During code reading, I noticed a do-nothing nWidth.
    
    It became obvious that this actually did nothing with
    commit 5b5995c05a17b1b16617ef8b477a657ce2a9406c
    Author: Noel Grandin on Thu Jul 20 10:15:07 2017 +0200
        loplugin:unusedfields in writerfilter
    
    Everything about that emulation looked completely wrong,
    so I've changed it so that it maps
    to LibreOffice's INSIDE/OUTSIDE - as vmlshape already does.
    
    Inside and Outside are essentially identical,
    so they should be emulated identically as well.
    
    Inside/Outside react the same way to "margin" as to "page",
    (and those are the only two choices)
    so both of those should also be emulated identically.
    
    make CppunitTest_sw_ooxmlexport22 \
        CPPUNIT_TEST_NAME=testTdf167770_marginInsideOutside
    
    Change-Id: If2ef6af13f4a4acf85d8ed981880fe631557ce9d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188834
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf167770_marginInsideOutside.docx 
b/sw/qa/extras/ooxmlexport/data/tdf167770_marginInsideOutside.docx
new file mode 100644
index 000000000000..78e52d8017c4
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/tdf167770_marginInsideOutside.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
index 7b9cee2d517a..ff62907e59e5 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
@@ -75,6 +75,67 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf166201_simplePosCM)
                          getProperty<sal_Int32>(getShape(1), 
u"VertOrientPosition"_ustr));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf167770_marginInsideOutside, 
"tdf167770_marginInsideOutside.docx")
+{
+    // given shapes and pictures that use inside / outside with the two 
options margin and page
+    uno::Reference<drawing::XShape> xShape(getShapeByName(u"Picture 1")); // 
page 1
+    CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_FRAME,
+                         getProperty<sal_Int16>(xShape, 
u"HoriOrientRelation"_ustr));
+    CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::LEFT,
+                         getProperty<sal_Int16>(xShape, u"HoriOrient"_ustr));
+    CPPUNIT_ASSERT(getProperty<bool>(xShape, u"PageToggle"_ustr));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xShape, 
u"LeftMargin"_ustr));
+
+    xShape.set(getShapeByName(u"Right Arrow 2")); // page 1
+    CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_FRAME,
+                         getProperty<sal_Int16>(xShape, 
u"HoriOrientRelation"_ustr));
+    CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::RIGHT,
+                         getProperty<sal_Int16>(xShape, u"HoriOrient"_ustr));
+    CPPUNIT_ASSERT(getProperty<bool>(xShape, u"PageToggle"_ustr));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xShape, 
u"RightMargin"_ustr));
+
+    xShape.set(getShapeByName(u"Picture 4")); // page 2
+    CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_PRINT_AREA,
+                         getProperty<sal_Int16>(xShape, 
u"HoriOrientRelation"_ustr));
+    CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::LEFT,
+                         getProperty<sal_Int16>(xShape, u"HoriOrient"_ustr));
+    CPPUNIT_ASSERT(getProperty<bool>(xShape, u"PageToggle"_ustr));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xShape, 
u"RightMargin"_ustr));
+
+    xShape.set(getShapeByName(u"Right Arrow 3")); // page 2
+    CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_PRINT_AREA,
+                         getProperty<sal_Int16>(xShape, 
u"HoriOrientRelation"_ustr));
+    CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::RIGHT,
+                         getProperty<sal_Int16>(xShape, u"HoriOrient"_ustr));
+    CPPUNIT_ASSERT(getProperty<bool>(xShape, u"PageToggle"_ustr));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xShape, 
u"LeftMargin"_ustr));
+
+    // When laying out that document:
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    const SwTwips nPageLeft = getXPath(pXmlDoc, "//page[1]/infos/bounds", 
"left").toInt32();
+    const SwTwips nPicture1Left
+        = getXPath(pXmlDoc, "//page[1]//fly/infos/bounds", "left").toInt32();
+    CPPUNIT_ASSERT_EQUAL(nPageLeft, nPicture1Left); // page 1: INSIDE == left
+
+    const SwTwips nPageRight = getXPath(pXmlDoc, "//page[1]/infos/bounds", 
"right").toInt32();
+    const SwTwips nArrow2Right
+        = getXPath(pXmlDoc, "//page[1]//SwAnchoredDrawObject/bounds", 
"right").toInt32();
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(nPageRight, nArrow2Right, 50); // page 1: 
OUTSIDE == right
+
+    const SwTwips nPageMarginRight
+        = getXPath(pXmlDoc, "//page[2]//body/infos/bounds", "right").toInt32();
+    const SwTwips nPicture4Right
+        = getXPath(pXmlDoc, "//page[2]//fly/infos/bounds", "right").toInt32();
+    CPPUNIT_ASSERT_EQUAL(nPageMarginRight, nPicture4Right); // page 2: INSIDE 
== right
+
+    const SwTwips nPageMarginLeft
+        = getXPath(pXmlDoc, "//page[2]//body/infos/bounds", "left").toInt32();
+    const SwTwips nArrow3Left
+        = getXPath(pXmlDoc, "//page[2]//SwAnchoredDrawObject/bounds", 
"left").toInt32();
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(nPageMarginLeft, nArrow3Left, 50); // page 2: 
OUTSIDE == left
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testTdf166975)
 {
     createSwDoc("WordOK.docx");
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx 
b/sw/source/filter/ww8/docxsdrexport.cxx
index fa8875494418..246e43742cac 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -996,10 +996,10 @@ void DocxSdrExport::startDMLAnchorInline(const 
SwFrameFormat* pFrameFormat, cons
         switch (rHoriOri.GetHoriOrient())
         {
             case text::HoriOrientation::LEFT:
-                alignH = "left";
+                alignH = rHoriOri.IsPosToggle() ? "inside" : "left";
                 break;
             case text::HoriOrientation::RIGHT:
-                alignH = "right";
+                alignH = rHoriOri.IsPosToggle() ? "outside" : "right";
                 break;
             case text::HoriOrientation::CENTER:
                 alignH = "center";
diff --git a/sw/source/writerfilter/dmapper/GraphicImport.cxx 
b/sw/source/writerfilter/dmapper/GraphicImport.cxx
index 4d397591acb1..14541cc61561 100644
--- a/sw/source/writerfilter/dmapper/GraphicImport.cxx
+++ b/sw/source/writerfilter/dmapper/GraphicImport.cxx
@@ -1228,17 +1228,38 @@ void GraphicImport::lcl_attribute(Id nName, const 
Value& rValue)
                             const bool bLeftSide
                                 = m_nHoriRelation == 
text::RelOrientation::PAGE_LEFT
                                     || m_nHoriRelation == 
text::RelOrientation::FRAME_LEFT;
+                            const bool bPageOrMargin
+                                = m_nHoriRelation == 
text::RelOrientation::PAGE_PRINT_AREA // margin
+                                    || m_nHoriRelation == 
text::RelOrientation::PAGE_FRAME; // page
 
-                            assert(bRightSide || bLeftSide
-                                || m_nHoriRelation == 
text::RelOrientation::PAGE_PRINT_AREA //margin
-                                || m_nHoriRelation == 
text::RelOrientation::PAGE_FRAME // page
+                            assert(bRightSide || bLeftSide || bPageOrMargin
                                 || m_nHoriRelation == 
text::RelOrientation::PRINT_AREA // column
-                                || m_nHoriRelation == 
text::RelOrientation::FRAME /*margin*/ );
+                                || m_nHoriRelation == 
text::RelOrientation::FRAME /*column*/ );
 
                             if (m_nHoriOrient == text::HoriOrientation::LEFT 
&& !bRightSide)
                                 m_nLeftMargin = 0;
                             else if (m_nHoriOrient == 
text::HoriOrientation::RIGHT && !bLeftSide)
                                 m_nRightMargin = 0;
+                            else if (m_nHoriOrient == 
text::HoriOrientation::INSIDE)
+                            {
+                                if (bPageOrMargin)
+                                {
+                                    m_bPageToggle = true;
+                                    m_nHoriOrient = 
text::HoriOrientation::LEFT;
+                                    m_nLeftMargin = 0;
+                                    m_nRightMargin = 0;
+                                }
+                            }
+                            else if (m_nHoriOrient == 
text::HoriOrientation::OUTSIDE)
+                            {
+                                if (bPageOrMargin)
+                                {
+                                    m_bPageToggle = true;
+                                    m_nHoriOrient = 
text::HoriOrientation::RIGHT;
+                                    m_nLeftMargin = 0;
+                                    m_nRightMargin = 0;
+                                }
+                            }
                         }
 
                         // Anchored: Word only supports at-char in that case.
@@ -1781,7 +1802,6 @@ rtl::Reference<SwXTextGraphicObject> 
GraphicImport::createGraphicObject(uno::Ref
                     uno::Any(true));
 
             xGraphicObject->setPropertyValue(getPropertyName(PROP_DECORATIVE), 
uno::Any(m_bDecorative));
-            sal_Int32 nWidth = - m_nLeftPosition;
             if (m_rGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
             {
                 if (m_nHoriRelation == text::RelOrientation::FRAME
@@ -1805,12 +1825,13 @@ rtl::Reference<SwXTextGraphicObject> 
GraphicImport::createGraphicObject(uno::Ref
                     const bool bLeftSide
                         = m_nHoriRelation == text::RelOrientation::PAGE_LEFT
                             || m_nHoriRelation == 
text::RelOrientation::FRAME_LEFT;
+                    const bool bPageOrMargin
+                        = m_nHoriRelation == 
text::RelOrientation::PAGE_PRINT_AREA // margin
+                            || m_nHoriRelation == 
text::RelOrientation::PAGE_FRAME; // page
 
-                    assert(bRightSide || bLeftSide
-                           || m_nHoriRelation == 
text::RelOrientation::PAGE_PRINT_AREA // margin
-                           || m_nHoriRelation == 
text::RelOrientation::PAGE_FRAME // page
+                    assert(bRightSide || bLeftSide || bPageOrMargin
                            || m_nHoriRelation == 
text::RelOrientation::PRINT_AREA // column
-                           || m_nHoriRelation == text::RelOrientation::FRAME 
/*margin*/ );
+                           || m_nHoriRelation == text::RelOrientation::FRAME 
/*column*/ );
 
                     if (m_nHoriOrient == text::HoriOrientation::LEFT && 
!bRightSide)
                         m_nLeftMargin = 0;
@@ -1818,8 +1839,20 @@ rtl::Reference<SwXTextGraphicObject> 
GraphicImport::createGraphicObject(uno::Ref
                         m_nRightMargin = 0;
                     else if (m_nHoriOrient == text::HoriOrientation::INSIDE)
                     {
-                        if (m_nHoriRelation == 
text::RelOrientation::PAGE_PRINT_AREA)
+                        if (bPageOrMargin)
+                        {
+                            m_bPageToggle = true;
+                            m_nHoriOrient = text::HoriOrientation::LEFT;
+                            m_nLeftMargin = 0;
+                            m_nRightMargin = 0;
+                        }
+                    }
+                    else if (m_nHoriOrient == text::HoriOrientation::OUTSIDE)
+                    {
+                        if (bPageOrMargin)
                         {
+                            m_bPageToggle = true;
+                            m_nHoriOrient = text::HoriOrientation::RIGHT;
                             m_nLeftMargin = 0;
                             m_nRightMargin = 0;
                         }
@@ -1837,23 +1870,6 @@ rtl::Reference<SwXTextGraphicObject> 
GraphicImport::createGraphicObject(uno::Ref
                 if( m_nVertOrient == text::VertOrientation::BOTTOM &&
                     m_nVertRelation == text::RelOrientation::PAGE_PRINT_AREA )
                     m_nBottomMargin = 0;
-                //adjust alignment
-                if( m_nHoriOrient == text::HoriOrientation::INSIDE &&
-                    m_nHoriRelation == text::RelOrientation::PAGE_FRAME )
-                {
-                    // convert 'left to page' to 'from left -<width> to page 
text area'
-                    m_nHoriOrient = text::HoriOrientation::NONE;
-                    m_nHoriRelation = text::RelOrientation::PAGE_PRINT_AREA;
-                    m_nLeftPosition = - nWidth;
-                }
-                else if( m_nHoriOrient == text::HoriOrientation::OUTSIDE &&
-                    m_nHoriRelation == text::RelOrientation::PAGE_FRAME )
-                {
-                    // convert 'right to page' to 'from left 0 to right page 
border'
-                    m_nHoriOrient = text::HoriOrientation::NONE;
-                    m_nHoriRelation = text::RelOrientation::PAGE_RIGHT;
-                    m_nLeftPosition = 0;
-                }
 
                 if (m_nVertRelation == text::RelOrientation::TEXT_LINE)
                 {

Reply via email to