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 <jluth@mail.com>
Tested-by: Justin Luth <jluth@mail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
index e7040b6..5699ecb 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 b5f6d33..4b0e199 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: