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 21abead6dbb143c291db0a49270e658a3e279d27 Author: Miklos Vajna <[email protected]> AuthorDate: Wed Jan 3 16:52:18 2024 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Jan 4 13:46:16 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. (cherry picked from commit ae974a9928aa435316f15626642d41c5dddafe99) Change-Id: I1e836531851ea5c9a983ae69da5be8a042cc6e39 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161606 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> 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 b3c2bceef5bb..e8ea5ebb89a1 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx @@ -2276,7 +2276,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 95b7ab141830..f77023514073 100644 --- a/sw/source/core/text/porlay.cxx +++ b/sw/source/core/text/porlay.cxx @@ -40,6 +40,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> @@ -665,6 +666,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)
