tdf#160984 sw continuous endnotes: fix the endnote continuation separator len

See e.g.
<https://bug-attachments.documentfoundation.org/attachment.cgi?id=194455>,
one remaining difference for the Word vs Writer note separator is the
length of the endnote continuation separator: it's body frame width in
Word, shorter in Writer.

Seems this is specific to the endnote continuation separator, i.e.
normal endnote separator, footnote separator and footnote continuation
separator is not affected. Additionally, it's really footnote vs
endnote: if you put footnotes to the end of the document in Word, it
still doesn't make the separator longer.

Fix the problem by extending SwFootnoteContFrame::PaintLine() to handle
this: if in Word compat mode, first note frame is a follow endnote
frame, then paint the longer separator.

The usual render test way via SfxObjectShell::GetPreviewMetaFile() only
works with 1st pages and we want to assert the 2nd page here, so go via
DocumentToGraphicRenderer, similar to how
EPUBExportFilter::CreateMetafiles() does it.

Change-Id: Ia0ba1138070f1a68f62ea6f5a6a85fbe0f76d482
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168263
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <[email protected]>
diff --git a/sw/qa/core/layout/data/endnote-cont-separator.docx b/sw/qa/core/layout/data/endnote-cont-separator.docx
new file mode 100644
index 0000000..2e01a5c
--- /dev/null
+++ b/sw/qa/core/layout/data/endnote-cont-separator.docx
Binary files differ
diff --git a/sw/qa/core/layout/paintfrm.cxx b/sw/qa/core/layout/paintfrm.cxx
index a5213c5..464979c 100644
--- a/sw/qa/core/layout/paintfrm.cxx
+++ b/sw/qa/core/layout/paintfrm.cxx
@@ -10,6 +10,7 @@
#include <swmodeltestbase.hxx>

#include <o3tl/string_view.hxx>
#include <svtools/DocumentToGraphicRenderer.hxx>

#include <docsh.hxx>
#include <unotxdoc.hxx>
@@ -188,6 +189,32 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineEndnoteSeparatorPosition)
    // i.e. the separator wasn't 2 inches long, but was shorter vs Word.
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2880), nEndnoteSeparatorLength);
}

CPPUNIT_TEST_FIXTURE(Test, testEndnoteContSeparator)
{
    // Given a document with a Word-style endnote continuation separator:
    createSwDoc("endnote-cont-separator.docx");

    // When rendering page 2:
    sal_Int32 nPage = 2;
    DocumentToGraphicRenderer aRenderer(mxComponent, /*bSelectionOnly=*/false);
    Size aSize = aRenderer.getDocumentSizeInPixels(nPage);
    Graphic aGraphic = aRenderer.renderToGraphic(nPage, aSize, aSize, COL_WHITE,
                                                 /*bExtOutDevData=*/false);
    auto& xMetaFile = const_cast<GDIMetaFile&>(aGraphic.GetGDIMetaFile());

    // Then make sure the separator length is correct:
    MetafileXmlDump aDumper;
    xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, xMetaFile);
    auto nEndnoteSeparatorStart = getXPath(pXmlDoc, "//polygon/point[1]"_ostr, "x"_ostr).toInt32();
    auto nEndnoteSeparatorEnd = getXPath(pXmlDoc, "//polygon/point[2]"_ostr, "x"_ostr).toInt32();
    sal_Int32 nEndnoteSeparatorLength = nEndnoteSeparatorEnd - nEndnoteSeparatorStart;
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 9360 (page print area width)
    // - Actual  : 2880 (2 inches)
    // i.e. the separator was too short vs Word.
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(9360), nEndnoteSeparatorLength);
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ftnfrm.hxx b/sw/source/core/inc/ftnfrm.hxx
index 558c494..7331ef0 100644
--- a/sw/source/core/inc/ftnfrm.hxx
+++ b/sw/source/core/inc/ftnfrm.hxx
@@ -51,6 +51,7 @@ public:
    SwFootnoteContFrame( SwFrameFormat*, SwFrame* );

    const SwFootnoteFrame* FindFootNote() const;
    const SwFootnoteFrame* FindEndNote() const;

    static inline SwFootnoteFrame* AppendChained(SwFrame* pThis, bool bDefaultFormat);
    static inline SwFootnoteFrame* PrependChained(SwFrame* pThis, bool bDefaultFormat);
diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx
index e83f4f8..5f0cc8a 100644
--- a/sw/source/core/layout/findfrm.cxx
+++ b/sw/source/core/layout/findfrm.cxx
@@ -698,6 +698,17 @@ const SwFootnoteFrame* SwFootnoteContFrame::FindFootNote() const
    return nullptr;
}

const SwFootnoteFrame* SwFootnoteContFrame::FindEndNote() const
{
    auto pRet = static_cast<const SwFootnoteFrame*>(Lower());
    if (pRet && pRet->GetAttr()->GetFootnote().IsEndNote())
    {
        return pRet;
    }

    return nullptr;
}

const SwPageFrame* SwRootFrame::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
{
    const SwPageFrame* pRet = nullptr;
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 754495f..c572585 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -5826,12 +5826,22 @@ void SwFootnoteContFrame::PaintLine( const SwRect& rRect,
            auto nPrintAreaTop = static_cast<double>(getFramePrintArea().Top());
            aPoint.setY(getFrameArea().Pos().Y() + nPrintAreaTop * 0.6);

            // Length is 2 inches, but don't paint outside the container frame.
            nWidth = o3tl::convert(2, o3tl::Length::in, o3tl::Length::twip);
            if (nWidth > nPrtWidth)
            const SwFootnoteFrame* pEndnoteFrame = FindEndNote();
            bool bEndnoteContinuation = pEndnoteFrame && pEndnoteFrame->GetMaster();
            if (bEndnoteContinuation)
            {
                // Endnote continuation separator is print area wide.
                nWidth = nPrtWidth;
            }
            else
            {
                // Length is 2 inches, but don't paint outside the container frame.
                nWidth = o3tl::convert(2, o3tl::Length::in, o3tl::Length::twip);
                if (nWidth > nPrtWidth)
                {
                    nWidth = nPrtWidth;
                }
            }
        }
        oLineRect.emplace(aPoint, Size(nWidth, rInf.GetLineWidth()));
    }