sw/CppunitTest_sw_core_text.mk              |    1 
 sw/qa/core/text/data/empty-superscript.docx |binary
 sw/qa/core/text/porlay.cxx                  |   60 ++++++++++++++++++++++++++++
 sw/qa/extras/ooxmlexport/ooxmlexport12.cxx  |    3 -
 sw/source/core/text/porlay.cxx              |   13 ++++++
 5 files changed, 76 insertions(+), 1 deletion(-)

New commits:
commit ae974a9928aa435316f15626642d41c5dddafe99
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Jan 3 16:52:18 2024 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Jan 3 17:57:58 2024 +0100

    tdf#158999 sw: fix bad zero text frame height with no text and auto 
superscript
    
    The problem was that the bugdoc had an empty paragraph with superscript
    (as char format) enabled and that was simply lost in the layout. Adding
    text to the paragraph or removing the superscript formatting worked
    around the problem.
    
    What happened is that SwSubFont::GetHeight() has a somewhat surprising
    explicit check for escapement, and there the CalcEscHeight() call might
    be invoked on an SwSubFont whose m_nOrgHeight is 0, while the intent is
    to just return the original height in case of automatic subscript or
    superscript.
    
    Fix the problem by checking the result of GetDefaultAscentAndHeight() in
    SwLineLayout::CalcLine(), and in case it would simply turn the line into
    an invisible one for an empty line with sub/subscript then go back to
    the already correctly calculated line height.
    
    This needed adjusting a test in CppunitTest_sw_ooxmlexport12 because the
    bugdoc there had such a paragraph, effectively testing if we lose
    content during layout, which is not wanted.
    
    Change-Id: I1e836531851ea5c9a983ae69da5be8a042cc6e39
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161588
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index 37b2fa566094..ce27696b3c4c 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -17,6 +17,7 @@ $(eval $(call 
gb_CppunitTest_add_exception_objects,sw_core_text, \
     sw/qa/core/text/frmform \
     sw/qa/core/text/itratr \
     sw/qa/core/text/itrform2 \
+    sw/qa/core/text/porlay \
     sw/qa/core/text/porrst \
     sw/qa/core/text/text \
 ))
diff --git a/sw/qa/core/text/data/empty-superscript.docx 
b/sw/qa/core/text/data/empty-superscript.docx
new file mode 100644
index 000000000000..2eea0b08715a
Binary files /dev/null and b/sw/qa/core/text/data/empty-superscript.docx differ
diff --git a/sw/qa/core/text/porlay.cxx b/sw/qa/core/text/porlay.cxx
new file mode 100644
index 000000000000..a2e94c586515
--- /dev/null
+++ b/sw/qa/core/text/porlay.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <swmodeltestbase.hxx>
+
+#include <memory>
+
+#include <IDocumentLayoutAccess.hxx>
+#include <doc.hxx>
+#include <frame.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+
+namespace
+{
+/// Covers sw/source/core/text/porlay.cxx fixes.
+class Test : public SwModelTestBase
+{
+public:
+    Test()
+        : SwModelTestBase("/sw/qa/core/text/data/")
+    {
+    }
+};
+
+CPPUNIT_TEST_FIXTURE(Test, testEmptySuperscript)
+{
+    // Given a document with 4 paragraphs, the 2nd is empty and is marked as 
superscript:
+    createSwDoc("empty-superscript.docx");
+
+    // When laying out that document:
+    calcLayout();
+
+    // Then make sure all 4 text frames have visible heights:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage = pLayout->GetLower()->DynCastPageFrame();
+    auto pText1 = pPage->FindFirstBodyContent()->DynCastTextFrame();
+    CPPUNIT_ASSERT_GREATER(static_cast<SwTwips>(0), 
pText1->getFrameArea().Height());
+    auto pText2 = pText1->GetNext()->DynCastTextFrame();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected greater than: 0
+    // - Actual  : 0
+    // i.e. the 2nd paragraph was not visible.
+    CPPUNIT_ASSERT_GREATER(static_cast<SwTwips>(0), 
pText2->getFrameArea().Height());
+    auto pText3 = pText2->GetNext()->DynCastTextFrame();
+    CPPUNIT_ASSERT_GREATER(static_cast<SwTwips>(0), 
pText3->getFrameArea().Height());
+    auto pText4 = pText3->GetNext()->DynCastTextFrame();
+    CPPUNIT_ASSERT_GREATER(static_cast<SwTwips>(0), 
pText4->getFrameArea().Height());
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
index 78ec87bafac6..c77936a8d66c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
@@ -2339,7 +2339,8 @@ 
DECLARE_OOXMLEXPORT_TEST(testTdf143384_tableInFoot_negativeMargins,
 {
     // There should be no crash during loading of the document
     // so, let's check just how much pages we have
-    CPPUNIT_ASSERT_EQUAL(1, getPages());
+    // Ideally this would be 1, matching Word.
+    CPPUNIT_ASSERT_EQUAL(2, getPages());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 0c247cbc8dc1..cae54845be7b 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -41,6 +41,7 @@
 #include <optional>
 #include <editeng/adjustitem.hxx>
 #include <editeng/charhiddenitem.hxx>
+#include <editeng/escapementitem.hxx>
 #include <svl/asiancfg.hxx>
 #include <svl/languageoptions.hxx>
 #include <tools/multisel.hxx>
@@ -656,6 +657,18 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf )
         sal_uInt16 nTmpAscent = GetAscent();
         sal_uInt16 nTmpHeight = Height();
         rLine.GetAttrHandler().GetDefaultAscentAndHeight( rInf.GetVsh(), 
*rInf.GetOut(), nTmpAscent, nTmpHeight );
+
+        short nEscapement = rLine.GetAttrHandler().GetFont()->GetEscapement();
+        if (GetAscent() && Height() && !nTmpAscent && !nTmpHeight
+            && (nEscapement == DFLT_ESC_AUTO_SUPER || nEscapement == 
DFLT_ESC_AUTO_SUB))
+        {
+            // We already had a calculated ascent + height, it would be 
cleared, automatic
+            // sub/superscript is set and we have no content. In this case it 
makes no sense to
+            // clear the old, correct ascent/height.
+            nTmpAscent = GetAscent();
+            nTmpHeight = Height();
+        }
+
         if (nTmpAscent < GetAscent() || GetAscent() <= 0)
             SetAscent(nTmpAscent);
         if (nTmpHeight < Height() || Height() <= 0)

Reply via email to