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) {