summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-02-09 08:26:21 +0100
committerMiklos Vajna <vmiklos@collabora.com>2023-02-09 08:25:07 +0000
commit00b9b33334791079c2dc26b1ed4c123450cabf7d (patch)
treead0eea7e915130a5c75f559573ac3a5e6941b224
parent25a16e7543965565a4227506003adc916deea500 (diff)
sw: call FormatEmpty() in SwTextFrame::Format() for split fly masters
The problem was that the text in the anchor frame of a split fly frame was duplicated on the old page and the new page as well. The reason for this seems to be that the master has no content and the follow has all the content (this is wanted), but then there is no code to explicitly clear the master. In other cases the master always gets some new content where portion building for that new content starts by throwing away the old portions. Once SwTextFrame::Format() and SwTextFrame::FormatEmpty() explicitly checks for these master anchors, the unwanted text in the master anchor disappears. An extra tweak is needed in SwTextFrame::PaintEmpty() to even hide the paragraph marker: this frame is empty but has a follow frame, so we should not show a paragraph marker there. Finally introduce a SwTextFrame::HasNonLastSplitFlyDrawObj() to be able to check for this "empty master anchor for split fly" case at a single place. With this <https://bugs.documentfoundation.org/attachment.cgi?id=185144> from <https://bugs.documentfoundation.org/show_bug.cgi?id=61594> gets laid out reasonably: the position is not perfect but we detect that only 1 para of the text frame fits page 1, we create a 2nd page and we correctly move exactly the text frame's 2nd para to page 2. Change-Id: I871bba2de5b829e667d5cfb1cbe0ba4cc2274edd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146680 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--sw/source/core/attr/formatflysplit.cxx12
-rw-r--r--sw/source/core/inc/txtfrm.hxx8
-rw-r--r--sw/source/core/text/frmform.cxx20
-rw-r--r--sw/source/core/text/frmpaint.cxx3
-rw-r--r--sw/source/core/text/itratr.cxx17
-rw-r--r--sw/source/core/text/itrform2.cxx11
-rw-r--r--sw/source/core/text/porrst.cxx4
7 files changed, 53 insertions, 22 deletions
diff --git a/sw/source/core/attr/formatflysplit.cxx b/sw/source/core/attr/formatflysplit.cxx
index bcbfcc2d5e96..904fd9a8bb5c 100644
--- a/sw/source/core/attr/formatflysplit.cxx
+++ b/sw/source/core/attr/formatflysplit.cxx
@@ -24,6 +24,18 @@
SwFormatFlySplit::SwFormatFlySplit(bool bSplit)
: SfxBoolItem(RES_FLY_SPLIT, bSplit)
{
+ // Once this pool item is true, a floating table (text frame + table inside it) is meant to
+ // split across multiple pages.
+ //
+ // The layout representation is the following:
+ //
+ // - We assume that the anchor type is at-para for such fly frames, and SwFlyAtContentFrame
+ // derives from SwFlowFrame to be able to split in general.
+ //
+ // - Both the master fly and the follow flys need an anchor. At the same time, we want all text
+ // of the anchor frame to be wrapped around the last follow fly frame, for Word compatibility.
+ // These are solved by splitting the anchor frame as many times as needed, always at text
+ // TextFrameIndex 0.
if (getenv("SW_FORCE_FLY_SPLIT"))
{
SetValue(true);
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index cb22ebc439f8..942867882626 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -332,6 +332,9 @@ class SW_DLLPUBLIC SwTextFrame final : public SwContentFrame
virtual void SwClientNotify(SwModify const& rModify, SfxHint const& rHint) override;
+ /// Like GetDrawObjs(), but limit to fly frames which are allowed to split.
+ std::vector<SwFlyAtContentFrame*> GetSplitFlyDrawObjs() const;
+
public:
virtual const SvxFormatBreakItem& GetBreakItem() const override;
@@ -784,8 +787,9 @@ public:
OUString GetCurWord(SwPosition const&) const;
sal_uInt16 GetScalingOfSelectedText(TextFrameIndex nStt, TextFrameIndex nEnd);
- /// Like GetDrawObjs(), but limit to fly frames which are allowed to split.
- std::vector<SwFlyAtContentFrame*> GetSplitFlyDrawObjs();
+ /// This text frame may have a split fly frames anchored to it. Is any of them a frame that has
+ /// a follow, i.e. not the last in a master -> follow 1 -> ... -> last follow chain?
+ bool HasNonLastSplitFlyDrawObj() const;
virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
};
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index f36d27e68ac5..329f9d784ed1 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -581,14 +581,11 @@ void SwTextFrame::AdjustFollow_( SwTextFormatter &rLine,
if (GetFollow()->IsDeleteForbidden())
return;
- for (const auto& pFlyFrame : GetSplitFlyDrawObjs())
+ if (HasNonLastSplitFlyDrawObj())
{
// If a fly frame is anchored to us that has a follow, then don't join the anchor.
// First those fly frames have to be joined.
- if (pFlyFrame->GetFollow())
- {
- return;
- }
+ return;
}
JoinFrame();
@@ -1838,7 +1835,18 @@ void SwTextFrame::Format( vcl::RenderContext* pRenderContext, const SwBorderAttr
return;
}
- const TextFrameIndex nStrLen(GetText().getLength());
+ TextFrameIndex nStrLen(GetText().getLength());
+
+ SwTextFrame* pFollow = GetFollow();
+ if (pFollow && pFollow->GetOffset() == mnOffset)
+ {
+ if (HasNonLastSplitFlyDrawObj())
+ {
+ // Non-last part of split fly anchor: consider this empty.
+ nStrLen = TextFrameIndex(0);
+ }
+ }
+
if ( nStrLen || !FormatEmpty() )
{
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index e09ad12373cb..461c8094c0ac 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -601,7 +601,8 @@ bool SwTextFrame::PaintEmpty( const SwRect &rRect, bool bCheck ) const
}
// Don't show the paragraph mark for collapsed paragraphs, when they are hidden
- if ( EmptyHeight( ) > 1 )
+ // No paragraph marker in the non-last part of a split fly anchor, either.
+ if ( EmptyHeight( ) > 1 && !HasNonLastSplitFlyDrawObj() )
{
SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), CH_PAR, 0, 1 );
aDrawInf.SetPos( aPos );
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index 105fc5e3af30..93ae3e4c6ed0 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -1451,10 +1451,10 @@ sal_uInt16 SwTextFrame::GetScalingOfSelectedText(
return o3tl::narrowing<sal_uInt16>( nWidth ? ((100 * aIter.GetFnt()->GetTextSize_( aDrawInf ).Height()) / nWidth ) : 0 );
}
-std::vector<SwFlyAtContentFrame*> SwTextFrame::GetSplitFlyDrawObjs()
+std::vector<SwFlyAtContentFrame*> SwTextFrame::GetSplitFlyDrawObjs() const
{
std::vector<SwFlyAtContentFrame*> aObjs;
- SwSortedObjs* pSortedObjs = GetDrawObjs();
+ const SwSortedObjs* pSortedObjs = GetDrawObjs();
if (!pSortedObjs)
{
return aObjs;
@@ -1479,6 +1479,19 @@ std::vector<SwFlyAtContentFrame*> SwTextFrame::GetSplitFlyDrawObjs()
return aObjs;
}
+bool SwTextFrame::HasNonLastSplitFlyDrawObj() const
+{
+ for (const auto& pFly : GetSplitFlyDrawObjs())
+ {
+ if (pFly->GetFollow())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
SwTwips SwTextNode::GetWidthOfLeadingTabs() const
{
SwTwips nRet = 0;
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 03ce7666c911..6c1f0c06a5a5 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1936,16 +1936,7 @@ TextFrameIndex SwTextFormatter::FormatLine(TextFrameIndex const nStartPos)
{
// Don't oversize the line in case of split flys, so we don't try to move the anchor
// of a precede fly forward, next to its follow.
- bool bHasNonLastFlySplitAnchored = false;
- for (const auto& pFlyFrame : m_pFrame->GetSplitFlyDrawObjs())
- {
- if (pFlyFrame->GetFollow())
- {
- bHasNonLastFlySplitAnchored = true;
- break;
- }
- }
- if (bHasNonLastFlySplitAnchored)
+ if (m_pFrame->HasNonLastSplitFlyDrawObj())
{
m_pCurr->SetRealHeight(GetFrameRstHeight());
}
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index 3a8dd51e014d..eb128eaa662e 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -410,7 +410,9 @@ bool SwTextFrame::FormatEmpty()
bool bCollapse = EmptyHeight( ) == 1 && IsCollapse( );
// sw_redlinehide: just disable FormatEmpty optimisation for now
- if (HasFollow() || GetMergedPara() || GetTextNodeFirst()->GetpSwpHints() ||
+ // Split fly frames: non-last parts of the anchor want this optimization to clear the old
+ // content.
+ if ((HasFollow() && mnOffset != GetFollow()->GetOffset()) || GetMergedPara() || GetTextNodeFirst()->GetpSwpHints() ||
nullptr != GetTextNodeForParaProps()->GetNumRule() ||
GetTextNodeFirst()->HasHiddenCharAttribute(true) ||
IsInFootnote() || ( HasPara() && GetPara()->IsPrepMustFit() ) )