sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_duplicate_compat15.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport18.cxx | 18 ++++++++++ writerfilter/inc/dmapper/GraphicZOrderHelper.hxx | 1 writerfilter/source/dmapper/GraphicHelpers.cxx | 6 ++- writerfilter/source/dmapper/GraphicImport.cxx | 10 +++++ 5 files changed, 34 insertions(+), 1 deletion(-)
New commits: commit a9c3955c13531045646df7c29a782980121e6960 Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Fri Jan 12 17:42:17 2024 -0500 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Jan 16 09:09:57 2024 +0100 tdf#159158 writerfilter: duplicate relativeHeights? last one wins [When MS Word 2019 round-trips a file with a duplicate relativeHeight it replaces them with unique relativeHeights in the export.] My THEORY is that bOldStyle should always be true for GraphicImport, so a follow-up commit will basically revert all of this, but at least if my theory is wrong, I'll still have fixed this problem. Notice that there are two things that feed into zOrder, the other being z-Index. I assume the very explicit code that says that (except for bOldStyle) first one wins must be the standard for z-Index. make CppunitTest_sw_ooxmlexport18 \ CPPUNIT_TEST_NAME=testTdf159158_zOrder_duplicate Change-Id: I842d016a7922427ce1290a7134d4e19fed52880f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161989 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_duplicate_compat15.docx b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_duplicate_compat15.docx new file mode 100644 index 000000000000..b39694ff9457 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_duplicate_compat15.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx index 0f3816a74336..e92994f8cd54 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx @@ -868,6 +868,24 @@ DECLARE_OOXMLEXPORT_TEST(testTdf155736, "tdf155736_PageNumbers_footer.docx") CPPUNIT_ASSERT_EQUAL(OUString("Page * of *"), parseDump("/root/page[2]/footer/txt/text()"_ostr)); } +DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_duplicate, "tdf159158_zOrder_duplicate_compat15.docx") +{ + // given a yellow star with relativeHeight 2, followed by an overlapping blue star also with 2 + uno::Reference<drawing::XShape> image1 = getShape(1), image2 = getShape(2); + sal_Int32 zOrder1, zOrder2; + OUString descr1, descr2; + uno::Reference<beans::XPropertySet> imageProperties1(image1, uno::UNO_QUERY); + imageProperties1->getPropertyValue( "ZOrder" ) >>= zOrder1; + imageProperties1->getPropertyValue( "Name" ) >>= descr1; + uno::Reference<beans::XPropertySet> imageProperties2(image2, uno::UNO_QUERY); + imageProperties2->getPropertyValue( "ZOrder" ) >>= zOrder2; + imageProperties2->getPropertyValue( "Name" ) >>= descr2; + CPPUNIT_ASSERT_EQUAL( sal_Int32( 0 ), zOrder1 ); // lower + CPPUNIT_ASSERT_EQUAL( sal_Int32( 1 ), zOrder2 ); // higher + CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Yellow"), descr1); + CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), descr2); // last one defined wins +} + DECLARE_OOXMLEXPORT_TEST(testTdf155903, "tdf155903.odt") { // Without the accompanying fix in place, this test would have crashed, diff --git a/writerfilter/inc/dmapper/GraphicZOrderHelper.hxx b/writerfilter/inc/dmapper/GraphicZOrderHelper.hxx index c6a308ddf819..2ad71c411420 100644 --- a/writerfilter/inc/dmapper/GraphicZOrderHelper.hxx +++ b/writerfilter/inc/dmapper/GraphicZOrderHelper.hxx @@ -19,6 +19,7 @@ public: void addItem(css::uno::Reference<css::beans::XPropertySet> const& props, sal_Int32 relativeHeight); sal_Int32 findZOrder(sal_Int32 relativeHeight, bool bOldStyle = false); + bool hasZOrder(sal_Int32 relativeHeight) { return m_items.count(relativeHeight) != 0; } private: using Items = std::map<sal_Int32, css::uno::Reference<css::beans::XPropertySet>>; diff --git a/writerfilter/source/dmapper/GraphicHelpers.cxx b/writerfilter/source/dmapper/GraphicHelpers.cxx index 67739d4986e5..d01ac5be3800 100644 --- a/writerfilter/source/dmapper/GraphicHelpers.cxx +++ b/writerfilter/source/dmapper/GraphicHelpers.cxx @@ -278,6 +278,10 @@ void GraphicZOrderHelper::addItem(uno::Reference<beans::XPropertySet> const& pro // The relativeHeight value in .docx is an arbitrary number, where only the relative ordering matters. // But in Writer, the z-order is index in 0..(numitems-1) range, so whenever a new item needs to be // added in the proper z-order, it is necessary to find the proper index. + +// The key to this function is that later on, when setPropertyValue("ZOrder", <returned sal_Int32>), +// SW also automatically increments ALL zOrders >= the one returned for this fly. +// Thus, getProperty PROP_Z_ORDER for relativeHeight "x" can return different values for itemZOrder. sal_Int32 GraphicZOrderHelper::findZOrder( sal_Int32 relativeHeight, bool bOldStyle ) { // std::map is iterated sorted by key @@ -292,7 +296,7 @@ sal_Int32 GraphicZOrderHelper::findZOrder( sal_Int32 relativeHeight, bool bOldSt if( it == m_items.end()) // we're topmost { if( m_items.empty()) - return 0; + return 0; // the lowest --it; itemZOrderOffset = 1; // after the topmost diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx index 4f0fd03b6db7..6fbc1728eb26 100644 --- a/writerfilter/source/dmapper/GraphicImport.cxx +++ b/writerfilter/source/dmapper/GraphicImport.cxx @@ -735,7 +735,17 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue) m_pImpl->m_bUseSimplePos = nIntValue > 0; break; case NS_ooxml::LN_CT_Anchor_relativeHeight: + { m_pImpl->m_zOrder = nIntValue; + + // Last one defined must win - opposite to what the existing code (for z-Index?) does. + GraphicZOrderHelper* pZOrderHelper = m_pImpl->m_rDomainMapper.graphicZOrderHelper(); + if (pZOrderHelper->hasZOrder(m_pImpl->m_zOrder) + && m_pImpl->m_rGraphicImportType != GraphicImportType::IMPORT_AS_DETECTED_INLINE) + { + ++m_pImpl->m_zOrder; + } + } break; case NS_ooxml::LN_CT_Anchor_behindDoc: if (nIntValue > 0)