sw/qa/extras/layout/data/tdf163230.fodt |  108 ++++++++++++++++++++++++++++++++
 sw/qa/extras/layout/layout3.cxx         |    9 ++
 sw/source/core/layout/tabfrm.cxx        |   48 ++++++++++++--
 3 files changed, 159 insertions(+), 6 deletions(-)

New commits:
commit b387a283c08a8efcd91e2386db41467435fb9856
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Oct 1 13:47:20 2024 +0500
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Oct 2 10:11:31 2024 +0200

    tdf#163230: make loop control hack more specific
    
    Commit 0c49aa58cfbb81073e34b1d47861a5a1fdd44114 (tdf#161508: add
    another loop control hack, 2024-06-11) only checked the frame area
    sizes and positions, but ignores the "valid" frags. It turns out,
    that these flags also needed when checking the loop condition.
    
    Change-Id: If155f2424b9a02cad6bf6d5c931dfccfb110d4c4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174310
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit d5c0b3f93d33ce1e3d320ee74d6b7b5c5d53d176)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174324
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/layout/data/tdf163230.fodt 
b/sw/qa/extras/layout/data/tdf163230.fodt
new file mode 100644
index 000000000000..5f100026d440
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf163230.fodt
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Sans" 
svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" 
style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" 
fo:hyphenation-keep="auto" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="36pt" style:writing-mode="page"/>
+   <style:text-properties style:font-name="Liberation Sans" 
fo:font-size="10pt" style:letter-kerning="false" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+  </style:default-style>
+  <style:default-style style:family="table">
+   <style:table-properties table:border-model="collapsing"/>
+  </style:default-style>
+  <style:default-style style:family="table-row">
+   <style:table-row-properties fo:keep-together="auto"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text">
+   <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="8pt" 
style:contextual-spacing="false" fo:line-height="108%" fo:text-align="start" 
style:justify-single-word="false" fo:orphans="2" fo:widows="2" 
style:writing-mode="lr-tb"/>
+  </style:style>
+  <style:default-page-layout>
+   <style:page-layout-properties style:writing-mode="lr-tb" 
style:layout-grid-standard-mode="true"/>
+  </style:default-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="Table1" style:family="table">
+   <style:table-properties style:width="11cm" fo:margin-left="0" 
fo:margin-top="0" fo:margin-bottom="0cm" table:align="left" 
style:writing-mode="page"/>
+  </style:style>
+  <style:style style:name="Table1.A" style:family="table-column">
+   <style:table-column-properties style:column-width="11cm"/>
+  </style:style>
+  <style:style style:name="Table1.1" style:family="table-row">
+   <style:table-row-properties style:min-row-height="1cm" 
fo:keep-together="always"/>
+  </style:style>
+  <style:style style:name="Table1.A1" style:family="table-cell">
+   <style:table-cell-properties fo:padding-left="1mm" fo:padding-right="1mm" 
fo:padding-top="0" fo:padding-bottom="0" fo:border="1pt solid #000000"/>
+  </style:style>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:margin-bottom="0pt" 
style:contextual-spacing="false" fo:orphans="0" fo:widows="0"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="11cm" fo:page-height="19cm" 
style:num-format="1" style:print-orientation="portrait" fo:margin-top="0" 
fo:margin-bottom="0cm" fo:margin-left="0" fo:margin-right="0" 
style:writing-mode="lr-tb"/>
+   <style:header-style>
+    <style:header-footer-properties fo:min-height="1cm" fo:margin-left="0" 
fo:margin-right="0" fo:margin-bottom="0cm" style:dynamic-spacing="true"/>
+   </style:header-style>
+   <style:footer-style>
+    <style:header-footer-properties fo:min-height="1cm" fo:margin-left="0" 
fo:margin-right="0" fo:margin-top="0" style:dynamic-spacing="true"/>
+   </style:footer-style>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1">
+   <style:header>
+    <text:p/>
+   </style:header>
+   <style:footer>
+    <text:p/>
+   </style:footer>
+  </style:master-page>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <table:table table:name="Table1" table:style-name="Table1">
+    <table:table-column table:style-name="Table1.A"/>
+    <table:table-row table:style-name="Table1.1">
+     <table:table-cell table:style-name="Table1.A1">
+      <text:p>1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st:</text:p>
+      <text:list>
+       <text:list-item>
+        <text:p>aaa</text:p>
+       </text:list-item>
+       <text:list-item>
+        <text:p>bbb</text:p>
+       </text:list-item>
+       <text:list-item>
+        <text:p>cccc</text:p>
+       </text:list-item>
+       <text:list-item>
+        <text:p>ddd</text:p>
+       </text:list-item>
+      </text:list>
+      <text:p text:style-name="P1">1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st.</text:p>
+      <text:p/>
+      <text:p text:style-name="P1">1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st</text:p>
+      <text:p/>
+      <text:p text:style-name="P1">1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st.</text:p>
+      <text:p/>
+      <text:p text:style-name="P1">1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st s:</text:p>
+      <text:p/>
+      <text:p/>
+      <text:p>1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st</text:p>
+      <text:p>1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st</text:p>
+      <text:p/>
+      <text:p>1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st</text:p>
+      <text:p>1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st</text:p>
+      <text:p>1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 
1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st 1_st</text:p>
+     </table:table-cell>
+    </table:table-row>
+    <table:table-row table:style-name="Table1.1">
+     <table:table-cell table:style-name="Table1.A1">
+      <text:p>2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 
2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 
2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 
2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 
2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd 2_nd</text:p>
+      <text:p/>
+     </table:table-cell>
+    </table:table-row>
+   </table:table>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index 831ce946bba2..3cb3731ed597 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -3565,6 +3565,15 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf152298)
     assertXPathContent(pDump, "//page[2]/body/tab/row[2]/cell[1]/txt"_ostr, 
u"10"_ustr);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, TestTdf163230)
+{
+    createSwDoc("tdf163230.fodt");
+    auto pExportDump = parseLayoutDump();
+    // The first row must split across pages, despite its "do not break" 
attribute, because it
+    // doesn't fit on the page. Before the fix, the document had only two 
pages.
+    assertXPath(pExportDump, "//page"_ostr, 3);
+}
+
 } // end of anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index b1e1783bc015..c92f72a63709 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2085,19 +2085,55 @@ public:
     bool OscillationDetected(const SwFrameAreaDefinition& rFrameArea);
 
 private:
-    std::vector<std::pair<SwRect, SwRect>> maFrameDatas;
+    // A partial copy of SwFrameAreaDefinition data
+    struct FrameData
+    {
+        SwRect frameArea;
+        SwRect framePrintArea;
+        bool frameAreaPositionValid;
+        bool frameAreaSizeValid;
+        bool framePrintAreaValid;
+
+        FrameData(const SwFrameAreaDefinition& src)
+            : frameArea(src.getFrameArea())
+            , framePrintArea(src.getFramePrintArea())
+            , frameAreaPositionValid(src.isFrameAreaPositionValid())
+            , frameAreaSizeValid(src.isFrameAreaSizeValid())
+            , framePrintAreaValid(src.isFramePrintAreaValid())
+        {
+        }
+
+        bool operator==(const SwFrameAreaDefinition& src) const
+        {
+            return frameArea == src.getFrameArea() && framePrintArea == 
src.getFramePrintArea()
+                   && frameAreaPositionValid == src.isFrameAreaPositionValid()
+                   && frameAreaSizeValid == src.isFrameAreaSizeValid()
+                   && framePrintAreaValid == src.isFramePrintAreaValid();
+        }
+    };
+    std::vector<FrameData> maFrameDatas;
 };
 
 bool PosSizeOscillationControl::OscillationDetected(const 
SwFrameAreaDefinition& rFrameArea)
 {
+    for (size_t i = 0; i < maFrameDatas.size(); ++i)
+    {
+        const auto& f = maFrameDatas[i];
+        if (f == rFrameArea)
+        {
+            SAL_WARN("sw.layout",
+                     "PosSize oscillation: frame " << i << " repeated; total 
frames " << maFrameDatas.size());
+            return true;
+        }
+    }
+
     if (maFrameDatas.size() == 20) // stack is full -> oscillation
+    {
+        SAL_WARN("sw.layout", "PosSize oscillation: max frames");
         return true;
+    }
 
-    for (const auto& [area, printArea] : maFrameDatas)
-        if (rFrameArea.getFrameArea() == area && 
rFrameArea.getFramePrintArea() == printArea)
-            return true;
-
-    maFrameDatas.emplace_back(rFrameArea.getFrameArea(), 
rFrameArea.getFramePrintArea());
+    maFrameDatas.emplace_back(rFrameArea);
     return false;
 }
 }

Reply via email to