sw/qa/extras/layout/data/tdf155177-1-min.odt |binary sw/qa/extras/layout/layout3.cxx | 57 +++++++++++++++++++++++++++ sw/source/core/text/txtfrm.cxx | 23 ---------- sw/source/core/text/widorp.cxx | 44 ++++++++++++++------ sw/source/core/text/widorp.hxx | 6 ++ 5 files changed, 94 insertions(+), 36 deletions(-)
New commits: commit fe89122c15744afcaccaa6d6628fa0436adf12e1 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Aug 25 14:20:34 2023 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Mon Aug 28 13:46:23 2023 +0200 tdf#155177 sw: fix 2-line bug in WidowsAndOrphans::WouldFit() The problem is that the check if the line contains a non-fly portion was only done in the loop, but the first line is already handled before the loop, so its non-fly portions are ignored and never less than 2 lines are moved, regardless of widow/orphan settings. (regression from commit 8c32cc17ce914188ea6783b0f79e19c5ddbf0b8d) Change-Id: Ic017a17233fcd58e22d54386650328f00fb3e9f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156121 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/qa/extras/layout/data/tdf155177-1-min.odt b/sw/qa/extras/layout/data/tdf155177-1-min.odt new file mode 100644 index 000000000000..68363860f05d Binary files /dev/null and b/sw/qa/extras/layout/data/tdf155177-1-min.odt differ diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx index 60da1bcbd9af..b390e6e38b9c 100644 --- a/sw/qa/extras/layout/layout3.cxx +++ b/sw/qa/extras/layout/layout3.cxx @@ -253,6 +253,63 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf120287c) assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout", 3); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf155177) +{ + createSwDoc("tdf155177-1-min.odt"); + + uno::Reference<beans::XPropertySet> xStyle(getStyles("ParagraphStyles")->getByName("Body Text"), + uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(210), getProperty<sal_Int32>(xStyle, "ParaTopMargin")); + + { + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "/root/page[2]/body/txt", 6); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[6]/SwParaPortion/SwLineLayout", 2); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[6]/SwParaPortion/SwLineLayout[2]", "portion", + "long as two lines."); + assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout", 3); + assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion", + "This paragraph is even longer so that "); + discardDumpedLayout(); + } + + // this should bring one line back + xStyle->setPropertyValue("ParaTopMargin", uno::Any(sal_Int32(200))); + + Scheduler::ProcessEventsToIdle(); + + { + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "/root/page[2]/body/txt", 7); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout", 1); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion", + "This paragraph is even longer so that "); + assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout", 2); + assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion", + "it is now three lines long though "); + discardDumpedLayout(); + } + + // this should bring second line back + xStyle->setPropertyValue("ParaTopMargin", uno::Any(sal_Int32(120))); + + Scheduler::ProcessEventsToIdle(); + + { + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "/root/page[2]/body/txt", 7); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout", 2); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion", + "This paragraph is even longer so that "); + assertXPath(pXmlDoc, "/root/page[2]/body/txt[7]/SwParaPortion/SwLineLayout[2]", "portion", + "it is now three lines long though "); + assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout", 1); + assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion", + "containing a single sentence."); + discardDumpedLayout(); + } +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf122878) { createSwDoc("tdf122878.docx"); diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index f4b90547173f..a86dfcaf175f 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -3882,28 +3882,7 @@ sal_uInt16 SwTextFrame::FirstLineHeight() const for (SwLineLayout const* pLine = pPara; pLine; pLine = pLine->GetNext()) { nHeight += pLine->Height(); - bool hasNonFly(false); - for (SwLinePortion const* pPortion = pLine->GetFirstPortion(); - pPortion; pPortion = pPortion->GetNextPortion()) - { - switch (pPortion->GetWhichPor()) - { - case PortionType::Fly: - case PortionType::Glue: - case PortionType::Margin: - break; - default: - { - hasNonFly = true; - break; - } - } - if (hasNonFly) - { - break; - } - } - if (hasNonFly) + if (::sw::FindNonFlyPortion(*pLine)) { break; } diff --git a/sw/source/core/text/widorp.cxx b/sw/source/core/text/widorp.cxx index 720a88a1102a..11e4193d7bd0 100644 --- a/sw/source/core/text/widorp.cxx +++ b/sw/source/core/text/widorp.cxx @@ -573,6 +573,30 @@ bool WidowsAndOrphans::FindWidows( SwTextFrame *pFrame, SwTextMargin &rLine ) return true; } +namespace sw { + +auto FindNonFlyPortion(SwLineLayout const& rLine) -> bool +{ + for (SwLinePortion const* pPortion = rLine.GetFirstPortion(); + pPortion; pPortion = pPortion->GetNextPortion()) + { + switch (pPortion->GetWhichPor()) + { + case PortionType::Fly: + case PortionType::Glue: + case PortionType::Margin: + break; + default: + { + return true; + } + } + } + return false; +}; + +} // namespace sw + bool WidowsAndOrphans::WouldFit( SwTextMargin &rLine, SwTwips &rMaxHeight, bool bTst, bool bMoveBwd ) { // Here it does not matter, if pFrame is swapped or not. @@ -592,6 +616,10 @@ bool WidowsAndOrphans::WouldFit( SwTextMargin &rLine, SwTwips &rMaxHeight, bool // tdf#146500 for MoveBwd(), want at least 1 line with non-fly bool hasNonFly(!bMoveBwd); + if (!hasNonFly) + { + hasNonFly = ::sw::FindNonFlyPortion(*rLine.GetCurr()); + } while (nMinLines > rLine.GetLineNr() || !hasNonFly) { if( !rLine.NextLine() ) @@ -602,21 +630,9 @@ bool WidowsAndOrphans::WouldFit( SwTextMargin &rLine, SwTwips &rMaxHeight, bool break; } nLineSum += rLine.GetLineHeight(); - for (SwLinePortion const* pPortion = rLine.GetCurr()->GetFirstPortion(); - !hasNonFly && pPortion; pPortion = pPortion->GetNextPortion()) + if (!hasNonFly) { - switch (pPortion->GetWhichPor()) - { - case PortionType::Fly: - case PortionType::Glue: - case PortionType::Margin: - break; - default: - { - hasNonFly = true; - break; - } - } + hasNonFly = ::sw::FindNonFlyPortion(*rLine.GetCurr()); } } diff --git a/sw/source/core/text/widorp.hxx b/sw/source/core/text/widorp.hxx index 193d27f633fe..996a7fc913bc 100644 --- a/sw/source/core/text/widorp.hxx +++ b/sw/source/core/text/widorp.hxx @@ -79,4 +79,10 @@ public: } }; +namespace sw { + +auto FindNonFlyPortion(SwLineLayout const& rLine) -> bool; + +} // namespace sw + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */