tdf#159158 writerfilter: relativeHeights of 0/1 are highest zOrder

Apparently 0 and 1 are the highest zOrders, 2 is the lowest, then 3...
At least, this seems to be true for relativeHeight.
Of course the documentation doesn't say anything about this,
but documents conclusively prove a maximum zOrder of 251,658,240.

[When MS Word 2019 round-trips a file with a relativeHeight of 0/1,
 it replaces them with the highest relativeHeight in the document,
 but values of 2+ are preserved.]

Notice that there are two things that feed into zOrder,
the other being z-index where negatives have special meaning
in this context, but no special meaning for 0 or 1.

Interestingly, relativeHeight is unsigned, but z-index is signed.
This ends up not being a problem with a maximum of 0F00 0000.

GOOD! LO normally exports starting from 2, but writes 0 if no zOrder.
// It seems 0 and 1 have special meaning:
// just start counting from 2 to avoid issues with that.

Proof case that 0 is higher than both 300 and 225,763,766
make CppunitTest_sw_ooxmlexport8 CPPUNIT_TEST_NAME=testN747461

make CppunitTest_sw_ooxmlexport18 \
    CPPUNIT_TEST_NAME=testTdf159158_zOrder_1and0equalA
make CppunitTest_sw_ooxmlexport18 \
    CPPUNIT_TEST_NAME=testTdf159158_zOrder_1and0equalB
make CppunitTest_sw_ooxmlexport18 \
    CPPUNIT_TEST_NAME=testTdf159158_zOrder_1and0max

Change-Id: I3540252ca5b0be3b2d847f1a3885adb850f39c39
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162038
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0equalA.docx b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0equalA.docx
new file mode 100644
index 0000000..6c4e287
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0equalA.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0equalB.docx b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0equalB.docx
new file mode 100644
index 0000000..ae79fda
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0equalB.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0max.docx b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0max.docx
new file mode 100644
index 0000000..edb1304
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_1and0max.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_max.docx b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_max.docx
new file mode 100644
index 0000000..4611974
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf159158_zOrder_max.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
index e92994f..76b0d04 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
@@ -886,6 +886,81 @@ DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_duplicate, "tdf159158_zOrder_dupli
    CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), descr2); // last one defined wins
}

DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_1and0equalA, "tdf159158_zOrder_1and0equalA.docx")
{
    // given a yellow star with relativeHeight 1, followed by an overlapping blue star with 0
    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); // 0 >= 1 (last one wins)
}

DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_1and0equalB, "tdf159158_zOrder_1and0equalB.docx")
{
    // given a yellow star with relativeHeight 0, followed by an overlapping blue star with 1
    // since they have the same zOrder value, last one wins, so same result as version A
    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); // 1 >= 0 (last one wins)
}

DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_1and0max, "tdf159158_zOrder_1and0max.docx")
{
    // given a yellow star with relativeHeight 251658240 (0F00 0000)
    // followed by an overlapping blue star with 0.
    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); // 0 >= 0F00 0000 (last one wins)
}

DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_max, "tdf159158_zOrder_max.docx")
{
    // given a yellow star with relativeHeight 251658241 (0F00 0001)
    // followed by an overlapping blue star with relativeHeight 251658240 (0F00 0000)
    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); // 0F00 0000 == 0F00 0001
}

DECLARE_OOXMLEXPORT_TEST(testTdf155903, "tdf155903.odt")
{
    // Without the accompanying fix in place, this test would have crashed,
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
index 0ea69e6..686371b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
@@ -170,15 +170,14 @@ after they are loaded.
    CPPUNIT_ASSERT_EQUAL( sal_Int32( 0 ), zOrder1 );
    CPPUNIT_ASSERT_EQUAL( sal_Int32( 1 ), zOrder2 );
    CPPUNIT_ASSERT_EQUAL( sal_Int32( 2 ), zOrder3 );
    CPPUNIT_ASSERT_EQUAL( OUString( "Black" ), descr1 );
    CPPUNIT_ASSERT_EQUAL( OUString( "Red" ), descr2 );
    CPPUNIT_ASSERT_EQUAL( OUString( "Green" ), descr3 );
    CPPUNIT_ASSERT_EQUAL(OUString("Red"), descr1);
    CPPUNIT_ASSERT_EQUAL(OUString("Green"), descr2);
    CPPUNIT_ASSERT_EQUAL(OUString("Black"), descr3); // tdf#159158: black should be on top

    // tdf#139915/tdf#159157 This was 826, but it should be -826
    CPPUNIT_ASSERT_EQUAL(sal_Int32(-826), getProperty<sal_Int32>(image1, "VertOrientPosition"));
    CPPUNIT_ASSERT_EQUAL(sal_Int32(-826), getProperty<sal_Int32>(image3, "VertOrientPosition"));
    sal_Int16 nExpected = text::RelOrientation::TEXT_LINE;
    CPPUNIT_ASSERT_EQUAL(nExpected, getProperty<sal_Int16>(image1, "VertOrientRelation"));

}

DECLARE_OOXMLEXPORT_TEST(testN750255, "n750255.docx")
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index 45d0462..c8a1e16 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -737,9 +737,13 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue)
        case NS_ooxml::LN_CT_Anchor_simplePos_attr:
            m_pImpl->m_bUseSimplePos = nIntValue > 0;
        break;
        case NS_ooxml::LN_CT_Anchor_relativeHeight:
        case NS_ooxml::LN_CT_Anchor_relativeHeight: // unsigned content
        {
            m_pImpl->m_zOrder = nIntValue;
            // undocumented - based on testing: both 0 and 1 are equivalent to the maximum 251658240
            if (nIntValue < 2/* || nIntValue > 0x0F000000*/)
                m_pImpl->m_zOrder = 0x0F000000;
            else
                m_pImpl->m_zOrder = nIntValue;
        }
        break;
        case NS_ooxml::LN_CT_Anchor_behindDoc: