sw/qa/extras/layout/data/table-in-section-split-loop.fodt | 161 ++++++++++++++ sw/qa/extras/layout/data/table-in-section-truncated.fodt | 161 ++++++++++++++ sw/qa/extras/layout/layout.cxx | 62 +++++ sw/source/core/inc/layouter.hxx | 1 sw/source/core/layout/layact.cxx | 24 +- sw/source/core/layout/layouter.cxx | 14 + sw/source/core/layout/tabfrm.cxx | 13 - sw/source/core/layout/wsfrm.cxx | 24 ++ 8 files changed, 453 insertions(+), 7 deletions(-)
New commits: commit ab87e684b150ba8f658bc2888cfb662f685c8515 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Thu Feb 27 19:44:26 2025 +0100 Commit: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> CommitDate: Tue Mar 4 18:50:29 2025 +0100 sw: layout: fix truncation of table in section There is a table in a section, split across 2 pages; now insert a page break that moves the section to page 2. In SwTabFrame::MakeAll(), on page 2, first the follow is joined, which grows the table frame but shrinks the section frame (removing the follow's height), then the table's upper is grown to LONG_MAX but with bTst=true so it doesn't actually change or invalidate the section frame, then in lcl_RecalcRow() almost no growth happens because the table frame already has accounted for the height of most of the table content. The section frame remains too small for the table, and the content is truncated... this problem can already be reproduced in OOo 3.3. When GetUpper()->Grow() returns some space, invalidate the upper if it's a section frame, then the next round will format the section. (Simply calling Grow() with bTst=false results in an opposite problem, where the section is too large.) Change-Id: I3cb3a5a38fbd7996fa9fcea9a6036f4260451a95 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182331 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit 154b58cfd76a8ad670d4aa25874eed66e3398a3e) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182354 Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> diff --git a/sw/qa/extras/layout/data/table-in-section-truncated.fodt b/sw/qa/extras/layout/data/table-in-section-truncated.fodt new file mode 100644 index 000000000000..238dcd18b1fb --- /dev/null +++ b/sw/qa/extras/layout/data/table-in-section-truncated.fodt @@ -0,0 +1,161 @@ +<?xml version='1.0' encoding='UTF-8'?> +<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:dc="http://purl.org/dc/eleme nts/1.1/" xmlns:ooo="http://openoffice.org/2004/office" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0 " xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><meta:creation-date>2025-02-27T18:20:34.001095028</meta:creation-date><dc:date>2025-02-27T18:27:39.896741375</dc:date><meta:editing-duration>PT6M11S</meta:editing-duration><meta:editing-cycles>4</meta:editing-cycles><meta:generator>CIB_OfficeDev/6.4.0.24$Linux_X86_64 LibreOffice_project/f75130dcf240f3fe0d11d4374e1ad4e36d92e416</meta:generator><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="4" meta:word-count="10" meta:character-count="53" meta:non-whitespace-character-count="47"/></office:meta> + <office:font-face-decls> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </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"/> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + </office:styles> + <office:automatic-styles> + <style:style style:name="Table1" style:family="table"> + <style:table-properties style:width="6.5cm" table:align="margins"/> + </style:style> + <style:style style:name="Table1.A" style:family="table-column"> + <style:table-column-properties style:column-width="6.5cm" style:rel-column-width="65535*"/> + </style:style> + <style:style style:name="Table1.A1" style:family="table-cell"> + <style:table-cell-properties fo:padding="0.097cm" fo:border="0.05pt solid #000000"/> + </style:style> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties/> + </style:style> + <style:style style:name="Sect1" style:family="section"> + <style:section-properties style:editable="false"> + <style:columns fo:column-count="1" fo:column-gap="0cm"/> + </style:section-properties> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="10.5cm" fo:page-height="14.801cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + </text:sequence-decls> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:p text:style-name="P3">before section</text:p> + <text:section text:style-name="Sect1" text:name="Section1"> + <table:table table:name="Table1" table:style-name="Table1"> + <table:table-column table:style-name="Table1.A"/> + <table:table-row> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p text:style-name="P1">in table in section</text:p> + <text:p text:style-name="P1"><text:soft-page-break/></text:p> + <text:p text:style-name="P1">end table</text:p> + </table:table-cell> + </table:table-row> + </table:table> + <text:p text:style-name="P1">end section</text:p> + </text:section> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 80809c0a5606..253dc9cc23fb 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -403,6 +403,47 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTableSplitBug) } } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTableInSectionTruncated) +{ + createSwDoc("table-in-section-truncated.fodt"); + + { + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "/root/page[1]/body/txt", 20); + assertXPath(pXmlDoc, "/root/page[1]/body/section/txt", 0); + assertXPath(pXmlDoc, "/root/page[1]/body/section/tab/row/cell/txt", 1); + assertXPath(pXmlDoc, "/root/page[2]/body/section/tab/row/cell/txt", 2); + assertXPath(pXmlDoc, "/root/page[2]/body/section/txt", 1); + assertXPath(pXmlDoc, "/root/page[2]/body/txt", 0); + + assertXPath(pXmlDoc, "/root/page[2]/body/section/infos/bounds", "bottom", u"11032"_ustr); + discardDumpedLayout(); + } + + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + pWrtShell->Down(false, 19); + dispatchCommand(mxComponent, u".uno:InsertPagebreak"_ustr, {}); + + { + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "/root/page[1]/body/txt", 20); + assertXPath(pXmlDoc, "/root/page[1]/body/section/txt", 0); + assertXPath(pXmlDoc, "/root/page[1]/body/section/tab/row/cell/txt", 0); + assertXPath(pXmlDoc, "/root/page[2]/body/txt", 1); + assertXPath(pXmlDoc, "/root/page[2]/body/section/tab/row/cell/txt", 3); + assertXPath(pXmlDoc, "/root/page[2]/body/section/txt", 1); + + assertXPath(pXmlDoc, "/root/page[2]/body/section/infos/bounds", "top", u"10369"_ustr); + assertXPath(pXmlDoc, "/root/page[2]/body/section/tab/infos/bounds", "top", u"10369"_ustr); + assertXPath(pXmlDoc, "/root/page[2]/body/section/tab/infos/bounds", "height", u"940"_ustr); + assertXPath(pXmlDoc, "/root/page[2]/body/section/txt/infos/bounds", "bottom", + u"11584"_ustr); + // problem was that the section bottom did not grow enough (only 11309) + assertXPath(pXmlDoc, "/root/page[2]/body/section/infos/bounds", "bottom", u"11584"_ustr); + discardDumpedLayout(); + } +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTableInSectionSplitLoop) { createSwDoc("table-in-section-split-loop.fodt"); diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index cdb234249ad8..3cdc8765099d 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -2957,8 +2957,17 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) } } if( IsInSct() || GetUpper()->IsInTab() || bFlySplit ) - nDeadLine = aRectFnSet.YInc( nDeadLine, - GetUpper()->Grow( LONG_MAX, true ) ); + { + auto const nGrow{GetUpper()->Grow(LONG_MAX, true)}; + if (nGrow != 0) + { + if (GetUpper()->IsSctFrame()) // what about table cell? + { + GetUpper()->InvalidateSize_(); + } + nDeadLine = aRectFnSet.YInc(nDeadLine, nGrow); + } + } { SwFrameDeleteGuard g(Lower()); // tdf#134965 prevent RemoveFollowFlowLine() commit 7b6c0248403561a417215d3c3bd488df8d0a5a16 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Tue Jan 28 18:10:55 2025 +0100 Commit: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> CommitDate: Tue Mar 4 18:50:21 2025 +0100 sw: layout: fix loop with table at the end of a section There is a table alone in a section, and there are 2 rows in the table, with the 2nd row split across page 1 and page 2. Due to space for another line of text being available, the table frame first does RemoveFollowFlowLine() etc and grows much higher than the section frame upper. Then in SwTabFrame::Join(), the section frame on page 2 is destroyed via SwSectionFrame::DelEmpty() so the section frame on page 1 doesn't have a follow. Then a SwTabFrame::Split() happens, and lcl_ShrinkCellsAndAllContent() ends up shrinking the section frame to 0 height (because there is no follow currently seen by SwSectionFrame::ToMaximize()), which is wrong as there is a 1st row in the table, so the table is still height 3712. If the table is directly in the body, then this works because the body frame doesn't shrink or grow. Then when the text frame in the 2nd row is formatted, it can't grow because SetRestrictTableGrowth(true) was called as a follow flow line exists, and in SwTabFrame::GrowFrame() nReal is -2777 due to the SwTabFrame being higher than the upper; the result is that the text frame is the same height/split at the same line as before SwTabFrame::MakeAll(). Then the whole thing happens again until eventually warn:sw.layout:875613:875613:sw/source/core/layout/layouter.cxx:194: Looping Louie: Stage 1! Try to detect situation of too high table in section and propagate Shrink only until the section is the same height as the table. Change-Id: If4b6db8b03d93a3227ad223203f2b0c3f73d3cc8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180857 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit f747378c4d5c3b2af0dc6ed2dc8cdbd2c4bf09c9) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182353 Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com> diff --git a/sw/qa/extras/layout/data/table-in-section-split-loop.fodt b/sw/qa/extras/layout/data/table-in-section-split-loop.fodt new file mode 100644 index 000000000000..c56254aba03a --- /dev/null +++ b/sw/qa/extras/layout/data/table-in-section-split-loop.fodt @@ -0,0 +1,161 @@ +<?xml version='1.0' encoding='UTF-8'?> +<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:c alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext: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:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns: meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><meta:initial-creator>gcc</meta:initial-creator><meta:creation-date>2025-01-28T13:52:39.048482856</meta:creation-date><dc:date>2025-01-28T14:44:09.682881525</dc:date><dc:creator>gcc</dc:creator><meta:editing-duration>PT12M50S</meta:editing-duration><meta:editing-cycles>7</meta:editing-cycles><meta:generator>LibreOfficeDev/25.8.0.0.alpha0$Linux_X86_64 LibreOffice_project/4b681ded88231674d8b7c133dd211f3c024a7118</meta:generator><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="2" meta:word-count="157" meta:character-count="834" meta:non-whitespace-character-count="663"/></office:meta> + <office:font-face-decls> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Lucida Sans1" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/> + </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:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:orphans="0" fo:widows="0" text:number-lines="false" text:line-number="0"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + </office:styles> + <office:automatic-styles> + <style:style style:name="Table1" style:family="table"> + <style:table-properties style:width="6.5cm" table:align="margins"/> + </style:style> + <style:style style:name="Table1.A" style:family="table-column"> + <style:table-column-properties style:column-width="6.5cm" style:rel-column-width="65535*"/> + </style:style> + <style:style style:name="Table1.1" style:family="table-row"> + <style:table-row-properties style:min-row-height="0.002cm"/> + </style:style> + <style:style style:name="Table1.A1" style:family="table-cell"> + <style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="0.5pt solid #000000" fo:border-top="0.5pt solid #000000" fo:border-bottom="none"/> + </style:style> + <style:style style:name="Table1.2" style:family="table-row"> + <style:table-row-properties style:min-row-height="1.644cm"/> + </style:style> + <style:style style:name="Table1.A2" style:family="table-cell"> + <style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.5pt solid #000000" fo:border-right="0.5pt solid #000000" fo:border-top="none" fo:border-bottom="0.5pt solid #000000"/> + </style:style> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Table_20_Contents"> + <style:text-properties/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Table_20_Contents"> + <style:text-properties/> + </style:style> + <style:style style:name="Sect1" style:family="section"> + <style:section-properties fo:background-color="#158466" text:dont-balance-text-columns="false" style:editable="false"> + <style:columns fo:column-count="1" fo:column-gap="0cm"/> + <style:background-image/> + </style:section-properties> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="10.5cm" fo:page-height="14.801cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"> + <style:drawing-page-properties draw:background-size="full"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + </text:sequence-decls> + <text:p text:style-name="Standard"/> + <text:p text:style-name="Standard"/> + <text:section text:style-name="Sect1" text:name="Section1"> + <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" office:value-type="string"> + <text:p text:style-name="P1">There<text:line-break/> is<text:line-break/> quite<text:line-break/> some<text:line-break/> text<text:line-break/> here<text:line-break/> to<text:line-break/> take<text:line-break/> up<text:line-break/> some<text:line-break/> but<text:line-break/> not<text:line-break/> all<text:line-break/> of<text:line-break/> the<text:line-break/> available<text:line-break/> space</text:p> + </table:table-cell> + </table:table-row> + <table:table-row table:style-name="Table1.2"> + <table:table-cell table:style-name="Table1.A2" office:value-type="string"> + <text:p text:style-name="P2">He heard quiet steps behind him. That didn't bode well. Who could be <text:soft-page-break/>following him this late at night and in this deadbeat part of town? And at this particular moment, just after he pulled off the big time and was making off with the greenbacks. Was there another crook who'd had the same idea, and was now watching him and waiting for a chance to grab the fruit of his labor? Or did the steps behind him mean that one of many law officers in town was on to him and just waiting to pounce and snap those cuffs on his wrists? He nervously looked all around. Suddenly he saw the alley. Like lightning he darted off to the left and disappeared between the two warehouses almost falling over the trash can lying in the middle of the sidewalk.</text:p> + </table:table-cell> + </table:table-row> + </table:table> + </text:section> + <text:p text:style-name="Standard"/> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 169bae98111f..80809c0a5606 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -8,10 +8,14 @@ */ #include <swmodeltestbase.hxx> + +#include <osl/process.h> +#include <comphelper/scopeguard.hxx> #include <comphelper/propertysequence.hxx> #include <vcl/scheduler.hxx> #include <svx/svddef.hxx> +#include <layouter.hxx> #include <fmtanchr.hxx> #include <fmtfsize.hxx> #include <fmtcntnt.hxx> @@ -399,6 +403,23 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTableSplitBug) } } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTableInSectionSplitLoop) +{ + createSwDoc("table-in-section-split-loop.fodt"); + + static OUString const var = u"TEST_NO_LOOP_CONTROLS"_ustr; + osl_setEnvironment(var.pData, u"1"_ustr.pData); + comphelper::ScopeGuard g([] { osl_clearEnvironment(var.pData); }); + + CPPUNIT_ASSERT_EQUAL(0, SwLayouter::GetLastLoopControlStage()); + + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false); + pWrtShell->Delete(); + + CPPUNIT_ASSERT_EQUAL(0, SwLayouter::GetLastLoopControlStage()); +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testRedlineFlysInBody) { createSwDoc(); diff --git a/sw/source/core/inc/layouter.hxx b/sw/source/core/inc/layouter.hxx index a3979cf4670a..34d025843ccd 100644 --- a/sw/source/core/inc/layouter.hxx +++ b/sw/source/core/inc/layouter.hxx @@ -102,6 +102,7 @@ public: void LoopControl( SwPageFrame* pPage ); void EndLoopControl(); + SW_DLLPUBLIC static int GetLastLoopControlStage(); void LoopingLouieLight( const SwDoc& rDoc, const SwTextFrame& rFrame ); static void CollectEndnotes( SwDoc* pDoc, SwSectionFrame* pSect ); diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx index 034e8a5f01e9..90bdff402d1a 100644 --- a/sw/source/core/layout/layact.cxx +++ b/sw/source/core/layout/layact.cxx @@ -512,7 +512,11 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext) // maximum number of loops like is done in the nested while loops. if (++nOuterLoopControlRuns > nOutermoopControlMax) { - SAL_WARN("sw", "SwLayAction::InternalAction has run too many loops"); + SAL_WARN("sw.layout", "SwLayAction::InternalAction has run too many loops"); + if (::std::getenv("TEST_NO_LOOP_CONTROLS")) + { + throw std::exception{}; // => fail test + } m_bInterrupt = true; } @@ -586,7 +590,11 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext) if ( ++nLoopControlRuns_1 > nLoopControlMax ) { - OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" ); + SAL_WARN("sw.layout", "LoopControl_1 in SwLayAction::InternalAction"); + if (::std::getenv("TEST_NO_LOOP_CONTROLS")) + { + throw std::exception{}; // => fail test + } break; } @@ -767,7 +775,11 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext) if ( ++nLoopControlRuns_3 > nLoopControlMax ) { - OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" ); + SAL_WARN("sw.layout", "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction"); + if (::std::getenv("TEST_NO_LOOP_CONTROLS")) + { + throw std::exception{}; // => fail test + } break; } @@ -786,7 +798,11 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext) if ( ++nLoopControlRuns_2 > nLoopControlMax ) { - OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" ); + SAL_WARN("sw.layout", "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction"); + if (::std::getenv("TEST_NO_LOOP_CONTROLS")) + { + throw std::exception{}; // => fail test + } break; } diff --git a/sw/source/core/layout/layouter.cxx b/sw/source/core/layout/layouter.cxx index 5bed8fcba2b5..a9dcd3a45e5d 100644 --- a/sw/source/core/layout/layouter.cxx +++ b/sw/source/core/layout/layouter.cxx @@ -34,11 +34,11 @@ class SwLooping { +public: sal_uInt16 mnMinPage; sal_uInt16 mnMaxPage; sal_uInt16 mnCount; sal_uInt16 mnLoopControlStage; -public: explicit SwLooping( SwPageFrame const * pPage ); void Control( SwPageFrame* pPage ); void Drastic( SwFrame* pFrame ); @@ -247,6 +247,14 @@ void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTextFrame& rFrame } } +// this is just for tests +static int g_LastLoopControlStage; + +int SwLayouter::GetLastLoopControlStage() +{ + return g_LastLoopControlStage; +} + bool SwLayouter::StartLooping( SwPageFrame const * pPage ) { if( mpLooping ) @@ -257,6 +265,10 @@ bool SwLayouter::StartLooping( SwPageFrame const * pPage ) void SwLayouter::EndLoopControl() { + if (mpLooping) + { + g_LastLoopControlStage = mpLooping->mnLoopControlStage; + } mpLooping.reset(); } diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index db42935339c8..3a84b5998bb5 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -3000,6 +3000,30 @@ SwTwips SwLayoutFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool bInfo ) } } + // A table frame may have grown beyond its parent frame after + // RemoveFollowFlowLine(), which is a problem in case the parent is a + // section: prevent shrinking the section smaller than the contained + // table. + if (IsTabFrame() + && static_cast<SwTabFrame*>(this)->IsRebuildLastLine() + && pToShrink == GetUpper() + && pToShrink->IsSctFrame()) // not required for page body, unsure about others + { + SwTwips nUpperMin{0}; + for (SwFrame const* pFrame = pToShrink->GetLower(); + pFrame != GetNext(); pFrame = pFrame->GetNext()) + { + nUpperMin += aRectFnSet.GetHeight(pFrame->getFrameArea()); + } + if (aRectFnSet.GetHeight(pToShrink->getFramePrintArea()) - nShrink < nUpperMin) + { + nShrink = aRectFnSet.GetHeight(pToShrink->getFramePrintArea()) - nUpperMin; + if (nShrink <= 0) + { + return 0; // nothing to do + } + } + } nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0; if( ( SwNeighbourAdjust::GrowAdjust == nAdjust || SwNeighbourAdjust::AdjustGrow == nAdjust ) && nReal < nShrink )