summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2024-04-07 18:23:52 +0500
committerMike Kaganski <mike.kaganski@collabora.com>2024-04-08 00:01:05 +0500
commita49596248ac9004d57d8bb6752c114444bce5121 (patch)
tree457c39185aaa6ff838557069d7a8a9d808fe72d4
parenti#84870: Add a unit test (diff)
downloadcore-a49596248ac9004d57d8bb6752c114444bce5121.tar.gz
core-a49596248ac9004d57d8bb6752c114444bce5121.zip
tdf#160526, tdf#160549: fix split conditions at page start
A single large object in a paragraph must be moved down, when the page has other content before this. On the other hand, there must not be moving down, when an unsuccessful attempt to move was already done (so the master frame is empty), or even the first time, when the frame is at the page body start. Change-Id: Ib8e2fe7b77c622d9cfac22722ca6b55dba7ad8ae Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165869 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/qa/extras/layout/data/tdf160526.fodt47
-rw-r--r--sw/qa/extras/layout/data/tdf160549.fodt60
-rw-r--r--sw/qa/extras/layout/layout2.cxx21
-rw-r--r--sw/source/core/text/frmform.cxx100
4 files changed, 215 insertions, 13 deletions
diff --git a/sw/qa/extras/layout/data/tdf160526.fodt b/sw/qa/extras/layout/data/tdf160526.fodt
new file mode 100644
index 000000000000..37cf73fb8e18
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf160526.fodt
@@ -0,0 +1,47 @@
+<?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:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" 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:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:writing-mode="lr-tb" style:flow-with-text="false"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties style:punctuation-wrap="hanging" style:line-break="strict" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true" fo:hyphenate="false"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic">
+ <style:graphic-properties draw:fill-color="#81d41a" draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="3cm" fo:min-width="12cm" style:run-through="foreground" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="25cm" fo:min-width="7cm" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="top" style:vertical-rel="baseline" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" 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="20pt" style:layout-grid-ruby-height="10pt" 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="0"/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page"/>
+ </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:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="1" draw:name="Shape 1" draw:style-name="gr1" svg:width="12cm" svg:height="3cm" svg:x="4cm" svg:y="0cm">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>Foo</text:p>
+ <text:p><draw:custom-shape text:anchor-type="as-char" draw:z-index="0" draw:name="Shape 2" draw:style-name="gr2" svg:width="7cm" svg:height="25cm">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/layout/data/tdf160549.fodt b/sw/qa/extras/layout/data/tdf160549.fodt
new file mode 100644
index 000000000000..fd8425eedd86
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf160549.fodt
@@ -0,0 +1,60 @@
+<?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:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" 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:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" 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:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Graphics" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Frame" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" fo:margin-left="2mm" fo:margin-right="2mm" fo:margin-top="2mm" fo:margin-bottom="2mm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" draw:fill="none" fo:padding="1.5mm" fo:border="0.06pt solid #000000"/>
+ </style:style>
+ <style:default-page-layout>
+ <style:page-layout-properties style:layout-grid-standard-mode="true"/>
+ </style:default-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
+ <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:wrap="none" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="right" style:horizontal-rel="page-content" fo:background-color="#ffffff" style:background-transparency="100%" draw:fill="solid" draw:fill-color="#ffffff" draw:opacity="0%" fo:padding="0pt" fo:border="none" style:writing-mode="lr-tb" draw:wrap-influence-on-position="once-successive"/>
+ </style:style>
+ <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Graphics">
+ <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:vertical-pos="top" style:vertical-rel="baseline" fo:border="none" style:mirror="none" fo:clip="rect(0pt, 0pt, 0pt, 0pt)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
+ </style:style>
+ <style:page-layout style:name="pm1" style:page-usage="mirrored">
+ <style:page-layout-properties fo:page-width="148mm" fo:page-height="210mm" style:num-format="1" style:print-orientation="landscape" fo:margin-top="15mm" fo:margin-bottom="15mm" fo:margin-left="15mm" fo:margin-right="15mm" style:writing-mode="lr-tb"/>
+ <style:header-style>
+ <style:header-footer-properties fo:min-height="5mm" fo:margin-bottom="1mm" style:dynamic-spacing="true"/>
+ </style:header-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><draw:frame draw:style-name="fr1" draw:name="Frame1" text:anchor-type="paragraph" svg:y="1mm" draw:z-index="0">
+ <draw:text-box fo:min-height="5mm" fo:min-width="4cm">
+ <text:p>foobar</text:p>
+ </draw:text-box>
+ </draw:frame></text:p>
+ </style:header>
+ </style:master-page>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:p><draw:custom-shape draw:style-name="fr2" draw:name="Image2" text:anchor-type="as-char" svg:width="8cm" svg:height="19cm" draw:z-index="1">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape><text:s/></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 55f2b966c6dc..ce6c7c56bb1e 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -2927,6 +2927,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, test_i84870)
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf160549)
+{
+ // Given a document with a large as-char object, alone in its paragraph, shifted down by a
+ // header object: it must not hang in a layout loop on import (similar to i84870, but not
+ // fixed by its fix)
+ createSwDoc("tdf160549.fodt");
+ // The object is the first in the document; it must not move to the next page
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf160526)
+{
+ // Given a document with a large as-char object, alone in its paragraph, shifted down by
+ // another body object
+ createSwDoc("tdf160526.fodt");
+ // It must move to the next page
+ CPPUNIT_ASSERT_EQUAL(2, getPages());
+ auto pExportDump = parseLayoutDump();
+ assertXPath(pExportDump, "//page[2]/body/txt/anchored/SwAnchoredDrawObject");
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 19dcb6e3ed5f..2e00f55f0988 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1003,6 +1003,53 @@ void SwTextFrame::ChangeOffset( SwTextFrame* pFrame, TextFrameIndex nNew )
MoveFlyInCnt( pFrame, nNew, TextFrameIndex(COMPLETE_STRING) );
}
+static bool isFirstVisibleFrameInBody(const SwTextFrame* pFrame)
+{
+ const SwFrame* pBodyFrame = pFrame->FindBodyFrame();
+ if (!pBodyFrame)
+ return false;
+ for (const SwFrame* pCur = pFrame;;)
+ {
+ if (pCur->GetPrev())
+ return false;
+ pCur = pCur->GetUpper();
+ assert(pCur); // We found pBodyFrame, right?
+ if (pCur->IsBodyFrame())
+ return true;
+ }
+}
+
+static bool hasFly(const SwTextFrame* pFrame)
+{
+ if (auto pDrawObjs = pFrame->GetDrawObjs(); pDrawObjs && pDrawObjs->size())
+ {
+ auto anchorId = (*pDrawObjs)[0]->GetFrameFormat().GetAnchor().GetAnchorId();
+ if (anchorId == RndStdIds::FLY_AT_PARA || anchorId == RndStdIds::FLY_AT_CHAR)
+ return true;
+ }
+ return false;
+}
+
+static bool hasAtPageFly(const SwFrame* pFrame)
+{
+ auto pPageFrame = pFrame->FindPageFrame();
+ if (!pPageFrame)
+ return false;
+ auto pPageDrawObjs = pPageFrame->GetDrawObjs();
+ if (pPageDrawObjs)
+ {
+ for (const auto pObject : *pPageDrawObjs)
+ if (pObject->GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ return true;
+ }
+ return false;
+}
+
+static bool isReallyEmptyMaster(const SwTextFrame* pFrame)
+{
+ return pFrame->IsEmptyMaster() && (!pFrame->GetDrawObjs() || !pFrame->GetDrawObjs()->size());
+}
+
void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
WidowsAndOrphans &rFrameBreak,
TextFrameIndex const nStrLen,
@@ -1028,20 +1075,48 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
!rFrameBreak.IsInside( rLine ) )
: rFrameBreak.IsBreakNow( rLine ) ) ) )
? 1 : 0;
+
+ SwTextFormatInfo& rInf = rLine.GetInfo();
+ const SwFrame* pBodyFrame = FindBodyFrame();
+
// i#84870
// no split of text frame, which only contains an as-character anchored object
- bool bOnlyContainsAsCharAnchoredObj =
+ bool bLoneAsCharAnchoredObj =
+ pBodyFrame &&
!IsFollow() && nStrLen == TextFrameIndex(1) &&
GetDrawObjs() && GetDrawObjs()->size() == 1 &&
(*GetDrawObjs())[0]->GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR;
- // Still try split text frame if we have columns.
- if (FindColFrame())
- bOnlyContainsAsCharAnchoredObj = false;
-
- if ( nNew && bOnlyContainsAsCharAnchoredObj )
+ if (bLoneAsCharAnchoredObj)
{
- nNew = 0;
+ // Still try split text frame if we have columns.
+ if (FindColFrame())
+ bLoneAsCharAnchoredObj = false;
+ // tdf#160526: only no split if there is no preceding frames on same page
+ else if (!isFirstVisibleFrameInBody(this))
+ bLoneAsCharAnchoredObj = false;
+ else
+ nNew = 0;
+ }
+ else if (nNew)
+ {
+ if (IsFollow())
+ {
+ // tdf#160549: do not split the frame at the very beginning again, if its master was empty
+ auto precede = static_cast<SwTextFrame*>(GetPrecede());
+ assert(precede);
+ auto precedeText = precede->DynCastTextFrame();
+ assert(precedeText);
+ if (isReallyEmptyMaster(precedeText))
+ nNew = 0;
+ }
+ else
+ {
+ // Do not split immediately in the beginning of page (unless there is an at-para or
+ // at-char or at-page fly, which pushes the rest down)
+ if (isFirstVisibleFrameInBody(this) && !hasFly(this) && !hasAtPageFly(pBodyFrame))
+ nNew = 0;
+ }
}
if ( nNew )
@@ -1049,8 +1124,6 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
SplitFrame( nEnd );
}
- const SwFrame *pBodyFrame = FindBodyFrame();
-
const tools::Long nBodyHeight = pBodyFrame ? ( IsVertical() ?
pBodyFrame->getFrameArea().Width() :
pBodyFrame->getFrameArea().Height() ) : 0;
@@ -1139,9 +1212,10 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
// content or contains no content, but has a numbering.
// i#84870 - No split, if text frame only contains one
// as-character anchored object.
- if ( !bOnlyContainsAsCharAnchoredObj &&
- (nStrLen > TextFrameIndex(0) ||
- bHasVisibleNumRule )
+ if (!bLoneAsCharAnchoredObj
+ && (bHasVisibleNumRule
+ || (nStrLen > TextFrameIndex(0)
+ && (nEnd != rLine.GetStart() || rInf.GetRest())))
)
{
SplitFrame( nEnd );
@@ -1165,7 +1239,7 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight;
//#i84870# - no shrink of text frame, if it only contains one as-character anchored object.
- if ( nChg < 0 && !bDelta && bOnlyContainsAsCharAnchoredObj )
+ if (nChg < 0 && !bDelta && bLoneAsCharAnchoredObj)
{
nChg = 0;
}