sw/qa/extras/ooxmlexport/ooxmlexport18.cxx | 11 ++++---- writerfilter/source/dmapper/GraphicImport.cxx | 32 +++++++++++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-)
New commits: commit 0b03dff37f4cad722819f36d5cf3bd39fb46d8ed Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Mon Jan 15 14:36:12 2024 -0500 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jan 22 14:20:31 2024 +0100 tdf#159158 writerfilter: relativeHeight always under z-index No matter what z-index I chose, it always ends up being above a relativeHeight. Since a heaven z-index is 0+, that means that all relativeHeight's need to be treated as negative. IsInHeaderFooter is a complication, because these are ALWAYS treated as if they are below the text, and yet behindDoc relativeHeights still need to be below their counterparts. While this algorithm could never cover all the situations (it would require transitioning to a sal_Int64 to do that) it should be fine for practical purposes. Plus, there are some unknown complications surrounding this. If I increase the behindDoc relativeHeight by 1 in tdf159158_zOrder_behindDocB.docx the yellow star actually moves on top of the blue star, which totally debunks my theory. RTF doesn't really use relativeHeight, but if it did, these changes should apply anyway. Change-Id: I62e1f9ae8fe6f99534a2a799692120508204c553 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162234 Reviewed-by: Justin Luth <jl...@mail.com> Tested-by: Justin Luth <jl...@mail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx index e7040b6d8d0b..5699ecbe7953 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx @@ -989,16 +989,15 @@ DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_zIndexWins, "tdf159158_zOrder_zInd CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, "ZOrder")); // lower CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, "ZOrder")); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getProperty<sal_Int32>(zOrder2, "ZOrder")); // higher - // If zOrder is defined by z-index, it seems that it goes above everything set by relativeHeight - if (isExported()) // not named on import - CPPUNIT_ASSERT_EQUAL_MESSAGE("DID YOU FIX ME? Frame1 really should be at the very top", - OUString("Frame1"), getProperty<OUString>(zOrder0,"Name")); // I'm puzzled. Somehow 0 is larger than 0EFF FFFF, but not larger than 0F00 0000 // and yet the maximum value was established earlier as 1DFF FFFF. Something doesn't line up. // Perhaps 0 and 1 don't mean maximum value at all, but something completely different? CPPUNIT_ASSERT_MESSAGE("DID YOU FIX ME? I really should be yellow, not blue", - "5-Point Star Yellow" != getProperty<OUString>(zOrder1, "Name")); - // CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), getProperty<OUString>(zOrder2,"Name")); + "5-Point Star Yellow" != getProperty<OUString>(zOrder0, "Name")); + // CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), getProperty<OUString>(zOrder1,"Name")); + // If zOrder is defined by z-index, it seems that it goes above everything set by relativeHeight + if (isExported()) // not named on import + CPPUNIT_ASSERT_EQUAL(OUString("Frame1"), getProperty<OUString>(zOrder2,"Name")); } DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_behindDocA, "tdf159158_zOrder_behindDocA.docx") diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx index b5f6d3385d58..4b0e199d1d17 100644 --- a/writerfilter/source/dmapper/GraphicImport.cxx +++ b/writerfilter/source/dmapper/GraphicImport.cxx @@ -210,7 +210,7 @@ public: sal_Int32 m_nTopPosition; bool m_bUseSimplePos; - sal_Int32 m_zOrder; + std::optional<sal_Int32> m_oZOrder; sal_Int16 m_nHoriOrient; sal_Int16 m_nHoriRelation; @@ -284,7 +284,6 @@ public: ,m_nLeftPosition(0) ,m_nTopPosition(0) ,m_bUseSimplePos(false) - ,m_zOrder(-1) ,m_nHoriOrient( text::HoriOrientation::NONE ) ,m_nHoriRelation( text::RelOrientation::FRAME ) ,m_nVertOrient( text::VertOrientation::NONE ) @@ -385,26 +384,33 @@ public: void applyZOrder(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const { - sal_Int32 nZOrder = m_zOrder; + std::optional<sal_Int32> oZOrder = m_oZOrder; bool bBehindText = m_bBehindDoc && !m_bOpaque; if (m_rGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE && !m_rDomainMapper.IsInShape()) { - nZOrder = 0; + oZOrder = SAL_MIN_INT32; + bBehindText = false; } - if (nZOrder >= 0) + if (oZOrder) { // tdf#120760 Send objects with behinddoc=true to the back. + // Only relativeHeight zOrders have been used if m_bBehindDoc is set, + // and they have already been set as negative values (to be below all z-indexes). + // Subtract even more so behindDoc relativeHeights will be behind + // other relativeHeights and negative z-indexes (needed for IsInHeaderFooter). + // relativeHeight removed 0x1E00 0000, so can subtract another 0x6200 0000 if (bBehindText) - nZOrder -= SAL_MAX_INT32; + oZOrder = *oZOrder - 0x62000000; // TODO: it is possible that RTF has been wrong all along as well. Always true here? const bool bLastDuplicateWins(!m_rDomainMapper.IsRTFImport() || m_rGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE); + GraphicZOrderHelper* pZOrderHelper = m_rDomainMapper.graphicZOrderHelper(); xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER), - uno::Any(pZOrderHelper->findZOrder(nZOrder, bLastDuplicateWins))); - pZOrderHelper->addItem(xGraphicObjectProperties, nZOrder); + uno::Any(pZOrderHelper->findZOrder(*oZOrder, bLastDuplicateWins))); + pZOrderHelper->addItem(xGraphicObjectProperties, *oZOrder); } } @@ -743,9 +749,15 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue) // undocumented - based on testing: both 0 and 1 are equivalent to the maximum 503316479 const sal_Int32 nMaxAllowed = 0x1DFFFFFF; if (nIntValue < 2 || nIntValue > nMaxAllowed) - m_pImpl->m_zOrder = nMaxAllowed; + m_pImpl->m_oZOrder = nMaxAllowed; else - m_pImpl->m_zOrder = nIntValue; + m_pImpl->m_oZOrder = nIntValue; + + // all relativeHeight objects (i.e. DOCX graphics that use GraphicImport), + // no matter how high their value, are below the lowest z-index shape (in same layer) + // so emulate that by pretending that they are below text (in the hell-layer). + // Please be assured that this does not actually place it in the hell-layer. + m_pImpl->m_oZOrder = *m_pImpl->m_oZOrder - (nMaxAllowed + 1); } break; case NS_ooxml::LN_CT_Anchor_behindDoc: