sw/qa/core/layout/calcmove.cxx | 31 +++++++++++++++++++++++++++++++ sw/source/core/layout/calcmove.cxx | 17 +++++++++++++++-- sw/source/core/layout/pagechg.cxx | 6 +++++- 3 files changed, 51 insertions(+), 3 deletions(-)
New commits: commit ba7199da2e6ec9d58475373f264326fbeb31f4bd Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Oct 2 08:15:45 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Oct 2 09:35:40 2024 +0200 tdf#156218 sw hide whitespace: fix increased page size on new para at doc end Create a document of 1 page, add empty paragraphs, so the next empty paragraph would create a second page. Hide whitespace, then add that paragraph: no second page is created. Seems this is a regression from commit 2c23d4ee1e1370b20560e47db7efaeaac1d94b26 (tdf#96515 sw Hide Whitespace: avoid creating unneeded page frames, 2015-12-16), because previously we had the opposite problem: creating new page frames all the time, even if the current page frame could grow. Fix the problem by: 1) In SwPageFrame::MakeAll(), fix the size of the page frame when switching to hide whitespace mode, so margins are not part of the height. At least the last paragraph of the doc is now near the bottom of the page, so it's more likely to create a new page. This means now we're back to still tweaking the size of the last page: but we used to determine the height based on just content and here we just ignore top/bottom margin. 2) In SwPageFrame::CheckPageHeightValidForHideWhitespace(), handle the top/bottom margins, otherwise we'll think that the page frame can still grow, when it should not. 3) Finally in SwPageFrame::MakeAll(), when we determine the height for non-last pages, the text frame for the new paragraph is already inserted, so limit the page frame height: if "content height" is more than "height - whitespace", then that limit should be the height, otherwise the page frame height will grow forever. Change-Id: I1125c31ec8b387df41c0881af98469d56ed773db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174368 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/layout/calcmove.cxx b/sw/qa/core/layout/calcmove.cxx index 8098dc238fc0..cd9ac954ac68 100644 --- a/sw/qa/core/layout/calcmove.cxx +++ b/sw/qa/core/layout/calcmove.cxx @@ -11,6 +11,9 @@ #include <test/xmldocptr.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> + namespace { /// Covers sw/source/core/layout/calcmove.cxx fixes. @@ -82,6 +85,34 @@ CPPUNIT_TEST_FIXTURE(Test, testIgnoreTopMarginFly) // is a Writer feature. CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4000), nParaTopMargin); } + +CPPUNIT_TEST_FIXTURE(Test, testHideWhitespaceGrowingLastPage) +{ + // Given a document with a full first page, then hiding whitespace: + createSwDoc(); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + while (getPages() == 1) + { + pWrtShell->SplitNode(); + } + pWrtShell->DelLeft(); + CPPUNIT_ASSERT_EQUAL(1, getPages()); + SwViewOption aViewOptions(*pWrtShell->GetViewOptions()); + aViewOptions.SetHideWhitespaceMode(true); + pWrtShell->ApplyViewOptions(aViewOptions); + + // When adding a new paragraph at doc end: + pWrtShell->SplitNode(); + + // Then make sure a new page is created: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 1 + // i.e. the page was growing instead of creating a new page when it already had a max size. + CPPUNIT_ASSERT_EQUAL(2, getPages()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx index 475420e32d78..8f99488ca86b 100644 --- a/sw/source/core/layout/calcmove.cxx +++ b/sw/source/core/layout/calcmove.cxx @@ -907,11 +907,18 @@ void SwPageFrame::MakeAll(vcl::RenderContext* pRenderContext) setFramePrintAreaValid(true); continue; } - else if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden() && pRootFrame->GetLastPage() != this) + else if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden()) { tools::Long height = 0; SwLayoutFrame *pBody = FindBodyCont(); - if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() ) + SwTwips nFullBodyHeight = pAttrs->GetSize().Height() - pAttrs->CalcTop() - pAttrs->CalcBottom(); + if (pRootFrame->GetLastPage() == this) + { + // Last page is only reduced by the top/bottom margin, the body frame height + // is not reduced. + height = nFullBodyHeight; + } + else if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() ) { // Columns have a fixed height height = pAttrs->GetSize().Height(); @@ -920,6 +927,12 @@ void SwPageFrame::MakeAll(vcl::RenderContext* pRenderContext) { // No need for borders. height = GetContentHeight(0, 0); + if (height > nFullBodyHeight) + { + // Content height would be larger than the show-whitespace body height, + // limit it. + height = nFullBodyHeight; + } } if (height > 0) diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index d086166caaef..1c49d6d2b8e5 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -65,6 +65,7 @@ #include <sortedobjs.hxx> #include <calbck.hxx> #include <txtfly.hxx> +#include <frmatr.hxx> using namespace ::com::sun::star; @@ -2561,7 +2562,10 @@ bool SwPageFrame::CheckPageHeightValidForHideWhitespace(SwTwips nDiff) // Content frame doesn't fit the actual size, check if it fits the nominal one. const SwFrameFormat* pPageFormat = static_cast<const SwFrameFormat*>(GetDep()); const Size& rPageSize = pPageFormat->GetFrameSize().GetSize(); - tools::Long nWhitespace = rPageSize.getHeight() - getFrameArea().Height(); + // Count what would be the max size for the body frame, ignoring top/bottom margin. + const SvxULSpaceItem& rULSpace = pPageFormat->GetULSpace(); + SwTwips nNominalHeight = rPageSize.getHeight() - rULSpace.GetUpper() - rULSpace.GetLower(); + tools::Long nWhitespace = nNominalHeight - getFrameArea().Height(); if (nWhitespace > -nDiff) { // It does: don't move it and invalidate our page frame so