sw/qa/extras/layout/data/tdf155177-1-min.odt |binary sw/qa/extras/layout/layout2.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 f49f87f628197bd58e5a5411a77615a677c0ff83 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Aug 25 14:20:34 2023 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Tue Sep 26 13:35:20 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> (cherry picked from commit fe89122c15744afcaccaa6d6628fa0436adf12e1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156197 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> 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/layout2.cxx b/sw/qa/extras/layout/layout2.cxx index 1e715b17097b..a29664cf8a13 100644 --- a/sw/qa/extras/layout/layout2.cxx +++ b/sw/qa/extras/layout/layout2.cxx @@ -2468,6 +2468,63 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf109077) CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(15), nTextBoxTop - nShapeTop); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf155177) +{ + createSwDoc("tdf155177-1-min.odt"); + + uno::Reference<beans::XPropertySet> xStyle(getStyles("ParagraphStyles")->getByName("Text Body"), + 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(SwLayoutWriter2, testUserFieldTypeLanguage) { // Set the system locale to German, the document will be English. diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index 5906c9c9d1f3..90b0a9e743e3 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -3802,28 +3802,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 b4fe1f9d4440..53d44d8f4b9f 100644 --- a/sw/source/core/text/widorp.cxx +++ b/sw/source/core/text/widorp.cxx @@ -527,6 +527,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. @@ -546,6 +570,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() ) @@ -556,21 +584,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: */