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)