sw/inc/pagedesc.hxx                                 |    2 
 sw/qa/core/layout/data/inline-endnote-position.docx |binary
 sw/qa/core/layout/ftnfrm.cxx                        |   20 ++++++++
 sw/source/core/layout/ftnfrm.cxx                    |   49 +++++++++++++++++++-
 sw/source/filter/ww8/docxattributeoutput.cxx        |   10 +++-
 5 files changed, 77 insertions(+), 4 deletions(-)

New commits:
commit dbc5e22e4e1ae730f70664472a3d4d72688d629e
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed May 22 13:56:40 2024 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu May 23 17:10:31 2024 +0200

    tdf#160984 sw continuous endnotes: fix the endnote container's top margin
    
    Comparing the Word vs Writer output for the bugdoc, the vertical
    position of the endnote text is not correct: the y pos should be larger
    than it is, see the red reference at e.g.
    <https://bug-attachments.documentfoundation.org/attachment.cgi?id=194265>.
    
    Seems this is caused by the different height of the rectangle around the
    endnote separator: the top margin is 124 twips in Writer, which is a
    hardcoded default from the SwPageFootnoteInfo ctor, while Word has this
    separator as a special character, inside a paragraph, which inherits the
    height of the default paragraph style.
    
    Fix the problem by extending sw::FootnoteSeparatorHeight() to also work
    from RES_POOLCOLL_STANDARD in the Word compat case. Note that it's not
    enough to take the font size (11pt in this case) from the paragraph
    style, we want to work with the real font, which knows the spacing
    between lines (15% in this case). SwFont::GetHeight() has this logic,
    it's also what e.g. SwTextFrame::FormatEmpty() uses.
    
    Note that footnotes have the same problem, but given that they grow from
    the bottom of the page, the text position was correct, even if the
    separator height is incorrect. Also, the separator line itself is not
    changed in this commit, we just make sure that the height is OK, so text
    below the line has the correct position.
    
    (cherry picked from commit d1ddd136a1b0e452492464d58715eaec144fd811)
    
    Change-Id: If1f4757908355abc81ee711de5ab9db4c751354c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167984
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/inc/pagedesc.hxx b/sw/inc/pagedesc.hxx
index ddc7e659a5bb..d9b58a4bb357 100644
--- a/sw/inc/pagedesc.hxx
+++ b/sw/inc/pagedesc.hxx
@@ -399,7 +399,7 @@ public:
 namespace sw {
     class PageFootnoteHint final : public SfxHint {};
 
-    SW_DLLPUBLIC SwTwips FootnoteSeparatorHeight(SwPageFootnoteInfo const&);
+    SW_DLLPUBLIC SwTwips FootnoteSeparatorHeight(SwDoc& rDoc, 
SwPageFootnoteInfo const&);
 }
 
 typedef boost::multi_index_container<
diff --git a/sw/qa/core/layout/data/inline-endnote-position.docx 
b/sw/qa/core/layout/data/inline-endnote-position.docx
new file mode 100644
index 000000000000..3905208f9f0e
Binary files /dev/null and 
b/sw/qa/core/layout/data/inline-endnote-position.docx differ
diff --git a/sw/qa/core/layout/ftnfrm.cxx b/sw/qa/core/layout/ftnfrm.cxx
index 1cf31809e5a7..a7640e26ca9a 100644
--- a/sw/qa/core/layout/ftnfrm.cxx
+++ b/sw/qa/core/layout/ftnfrm.cxx
@@ -102,4 +102,24 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineEndnoteAndSection)
     CPPUNIT_ASSERT_EQUAL(2, nToplevelSections);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testInlineEndnotePosition)
+{
+    // Given a document, ContinuousEndnotes is true:
+    createSwDoc("inline-endnote-position.docx");
+
+    // When laying out that document:
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    // Then make sure the endnote separator (line + spacing around it) is 
large enough, so the
+    // endnote text below the separator has the correct position:
+    sal_Int32 nEndnoteContTopMargin
+        = parseDump("//column/ftncont/infos/prtBounds"_ostr, 
"top"_ostr).toInt32();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 269
+    // - Actual  : 124
+    // i.e. the top margin wasn't the default font size with its spacing, but 
the Writer default,
+    // which shifted endnote text up, incorrectly.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(269), nEndnoteContTopMargin);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index 61a8385d51fc..46312f9f4e89 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -42,9 +42,41 @@
 #include <sal/log.hxx>
 #include <IDocumentSettingAccess.hxx>
 #include <flyfrm.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <docsh.hxx>
+#include <poolfmt.hxx>
+#include <swfntcch.hxx>
+#include <wrtsh.hxx>
 
 #define ENDNOTE 0x80000000
 
+namespace
+{
+/// Calculates the height of the line that hosts the separator line (the top 
margin of the
+/// container), based on the default paragraph style in rDoc.
+bool FootnoteSeparatorHeightFromParagraph(SwDoc& rDoc, SwTwips& rHeight)
+{
+        const SwTextFormatColl* pDefaultParaFormat
+            = 
rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD);
+        if (!pDefaultParaFormat)
+        {
+            return false;
+        }
+
+        SwViewShell* pSh = rDoc.GetDocShell()->GetWrtShell();
+        if (!pSh)
+        {
+            return false;
+        }
+
+        SwFontAccess aFontAccess(pDefaultParaFormat, pSh);
+        SwFont aFont(aFontAccess.Get()->GetFont());
+        OutputDevice& rOut = pSh->GetRefDev();
+        rHeight = aFont.GetHeight(pSh, rOut);
+        return true;
+}
+}
+
 /// Search the position of an attribute in the FootnoteArray at the document,
 /// because all footnotes are located there, ordered by their index.
 static sal_uLong lcl_FindFootnotePos( const SwDoc *pDoc, const SwTextFootnote 
*pAttr )
@@ -222,8 +254,20 @@ static tools::Long lcl_Undersize( const SwFrame* pFrame )
 
 namespace sw {
 
-SwTwips FootnoteSeparatorHeight(SwPageFootnoteInfo const& rInf)
+SwTwips FootnoteSeparatorHeight(SwDoc& rDoc, SwPageFootnoteInfo const& rInf)
 {
+    const IDocumentSettingAccess& rIDSA = rDoc.getIDocumentSettingAccess();
+    if (rIDSA.get(DocumentSettingId::CONTINUOUS_ENDNOTES))
+    {
+        // Word style: try to calculate the height from the default para 
format.
+        SwTwips nHeight{};
+        if (FootnoteSeparatorHeightFromParagraph(rDoc, nHeight))
+        {
+            return nHeight;
+        }
+    }
+
+    // Writer style: calculate from the page style.
     return rInf.GetTopDist() + rInf.GetBottomDist() + rInf.GetLineWidth();
 }
 
@@ -235,7 +279,8 @@ void SwFootnoteContFrame::Format( vcl::RenderContext* 
/*pRenderContext*/, const
     // calculate total border, only one distance to the top
     const SwPageFrame* pPage = FindPageFrame();
     const SwPageFootnoteInfo &rInf = pPage->GetPageDesc()->GetFootnoteInfo();
-    const SwTwips nBorder = sw::FootnoteSeparatorHeight(rInf);
+    SwDoc* pDoc = getRootFrame()->GetCurrShell()->GetDoc();
+    const SwTwips nBorder = sw::FootnoteSeparatorHeight(*pDoc, rInf);
     SwRectFnSet aRectFnSet(this);
 
     if ( !isFramePrintAreaValid() )
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 9b8c4dbceb2b..3201321a6328 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -8722,7 +8722,15 @@ void DocxAttributeOutput::FootnotesEndnotes( bool 
bFootnotes )
         bSeparator = rFootnoteInfo.GetLineStyle() != SvxBorderLineStyle::NONE
                   && rFootnoteInfo.GetLineWidth() > 0
                   && double(rFootnoteInfo.GetWidth()) > 0;
-        nHeight = sw::FootnoteSeparatorHeight(rFootnoteInfo);
+        nHeight = sw::FootnoteSeparatorHeight(m_rExport.m_rDoc, rFootnoteInfo);
+
+        const IDocumentSettingAccess& rIDSA = 
m_rExport.m_rDoc.getIDocumentSettingAccess();
+        if (rIDSA.get(DocumentSettingId::CONTINUOUS_ENDNOTES))
+        {
+            // Don't request separator if this is a Word-style separator, 
which is handled at a
+            // layout level.
+            nHeight = 0;
+        }
     }
 
     WriteFootnoteSeparatorHeight(m_pSerializer, nHeight);

Reply via email to