1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <layouter.hxx>
23 #include <sectfrm.hxx>
24 #include <pagefrm.hxx>
27 #include <IDocumentLayoutAccess.hxx>
29 #include <movedfwdfrmsbyobjpos.hxx>
30 #include "objstmpconsiderwrapinfl.hxx"
31 #include <osl/diagnose.h>
33 #define LOOP_DETECT 250
40 sal_uInt16 mnLoopControlStage
;
42 explicit SwLooping( SwPageFrame
const * pPage
);
43 void Control( SwPageFrame
* pPage
);
44 void Drastic( SwFrame
* pFrame
);
45 bool IsLoopingLouieLight() const { return mnCount
> LOOP_DETECT
- 30; };
50 SwLayouter
* m_pMaster
;
51 SwSectionFrame
* m_pSect
;
52 std::unique_ptr
<SwFootnoteFrames
> m_pEndArr
;
54 explicit SwEndnoter( SwLayouter
* pLay
)
55 : m_pMaster( pLay
), m_pSect( nullptr ) {}
56 void CollectEndnotes( SwSectionFrame
* pSct
);
57 void CollectEndnote( SwFootnoteFrame
* pFootnote
);
58 const SwSectionFrame
* GetSect() const { return m_pSect
; }
59 void InsertEndnotes();
60 bool HasEndnotes() const { return m_pEndArr
&& !m_pEndArr
->empty(); }
63 void SwEndnoter::CollectEndnotes( SwSectionFrame
* pSct
)
65 OSL_ENSURE( pSct
, "CollectEndnotes: Which section?" );
68 else if( pSct
!= m_pSect
)
70 m_pSect
->CollectEndnotes( m_pMaster
);
73 void SwEndnoter::CollectEndnote( SwFootnoteFrame
* pFootnote
)
75 if( m_pEndArr
&& m_pEndArr
->end() != std::find( m_pEndArr
->begin(), m_pEndArr
->end(), pFootnote
) )
78 if( pFootnote
->GetUpper() )
80 // pFootnote is the master, he incorporates its follows
81 SwFootnoteFrame
*pNxt
= pFootnote
->GetFollow();
84 SwFrame
*pCnt
= pNxt
->ContainsAny();
88 { SwFrame
*pNxtCnt
= pCnt
->GetNext();
90 pCnt
->Paste( pFootnote
);
96 OSL_ENSURE( pNxt
->Lower() && pNxt
->Lower()->IsSctFrame(),
97 "Endnote without content?" );
99 SwFrame::DestroyFrame(pNxt
);
101 pNxt
= pFootnote
->GetFollow();
103 if( pFootnote
->GetMaster() )
109 for (SwFootnoteFrame
* pEndFootnote
: *m_pEndArr
)
111 if( pEndFootnote
->GetAttr() == pFootnote
->GetAttr() )
113 SwFrame::DestroyFrame(pFootnote
);
119 m_pEndArr
.reset( new SwFootnoteFrames
); // deleted from the SwLayouter
120 m_pEndArr
->push_back( pFootnote
);
123 void SwEndnoter::InsertEndnotes()
127 if( !m_pEndArr
|| m_pEndArr
->empty() )
132 OSL_ENSURE( m_pSect
->Lower() && m_pSect
->Lower()->IsFootnoteBossFrame(),
133 "InsertEndnotes: Where's my column?" );
134 SwFrame
* pRef
= m_pSect
->FindLastContent( SwFindMode::MyLast
);
135 SwFootnoteBossFrame
*pBoss
= pRef
? pRef
->FindFootnoteBossFrame()
136 : static_cast<SwFootnoteBossFrame
*>(m_pSect
->Lower());
137 pBoss
->MoveFootnotes_( *m_pEndArr
);
142 SwLooping::SwLooping( SwPageFrame
const * pPage
)
145 mnMinPage
= pPage
->GetPhyPageNum();
146 mnMaxPage
= mnMinPage
;
148 mnLoopControlStage
= 0;
151 void SwLooping::Drastic( SwFrame
* pFrame
)
155 pFrame
->ValidateThisAndAllLowers( mnLoopControlStage
);
156 pFrame
= pFrame
->GetNext();
160 void SwLooping::Control( SwPageFrame
* pPage
)
164 const sal_uInt16 nNew
= pPage
->GetPhyPageNum();
165 if (nNew
> mnMaxPage
)
167 if (nNew
< mnMinPage
)
172 mnLoopControlStage
= 0;
174 else if (nNew
> mnMinPage
+ 2)
176 mnMinPage
= nNew
- 2;
179 mnLoopControlStage
= 0;
181 else if (++mnCount
> LOOP_DETECT
)
183 #if OSL_DEBUG_LEVEL > 1
184 static bool bNoLouie
= false;
189 // FME 2007-08-30 #i81146# new loop control
190 SAL_WARN("sw.layout", "Looping Louie: Stage " << (mnLoopControlStage
+ 1) << "!");
192 Drastic( pPage
->Lower() );
193 if (nNew
> mnMinPage
&& pPage
->GetPrev())
194 Drastic( static_cast<SwPageFrame
*>(pPage
->GetPrev())->Lower() );
195 if (nNew
< mnMaxPage
&& pPage
->GetNext())
196 Drastic( static_cast<SwPageFrame
*>(pPage
->GetNext())->Lower() );
198 ++mnLoopControlStage
;
203 SwLayouter::SwLayouter()
207 SwLayouter::~SwLayouter()
211 void SwLayouter::CollectEndnotes_( SwSectionFrame
* pSect
)
214 mpEndnoter
.reset(new SwEndnoter( this ));
215 mpEndnoter
->CollectEndnotes( pSect
);
218 bool SwLayouter::HasEndnotes() const
220 return mpEndnoter
->HasEndnotes();
223 void SwLayouter::CollectEndnote( SwFootnoteFrame
* pFootnote
)
225 mpEndnoter
->CollectEndnote( pFootnote
);
228 void SwLayouter::InsertEndnotes( SwSectionFrame
const * pSect
)
230 if( !mpEndnoter
|| mpEndnoter
->GetSect() != pSect
)
232 mpEndnoter
->InsertEndnotes();
235 void SwLayouter::LoopControl( SwPageFrame
* pPage
)
238 mpLooping
->Control( pPage
);
241 void SwLayouter::LoopingLouieLight( const SwDoc
& rDoc
, const SwTextFrame
& rFrame
)
243 if ( mpLooping
&& mpLooping
->IsLoopingLouieLight() )
245 SAL_WARN("sw.layout", "Looping Louie (Light): Fixating fractious frame");
246 SwLayouter::InsertMovedFwdFrame( rDoc
, rFrame
, rFrame
.FindPageFrame()->GetPhyPageNum() );
250 bool SwLayouter::StartLooping( SwPageFrame
const * pPage
)
254 mpLooping
.reset(new SwLooping( pPage
));
258 void SwLayouter::EndLoopControl()
263 void SwLayouter::CollectEndnotes( SwDoc
* pDoc
, SwSectionFrame
* pSect
)
265 assert(pDoc
&& "No doc, no fun");
266 if( !pDoc
->getIDocumentLayoutAccess().GetLayouter() )
267 pDoc
->getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
268 pDoc
->getIDocumentLayoutAccess().GetLayouter()->CollectEndnotes_( pSect
);
271 bool SwLayouter::Collecting( SwDoc
* pDoc
, SwSectionFrame
const * pSect
, SwFootnoteFrame
* pFootnote
)
273 if( !pDoc
->getIDocumentLayoutAccess().GetLayouter() )
275 SwLayouter
*pLayouter
= pDoc
->getIDocumentLayoutAccess().GetLayouter();
276 if( pLayouter
->mpEndnoter
&& pLayouter
->mpEndnoter
->GetSect() && pSect
&&
277 ( pLayouter
->mpEndnoter
->GetSect()->IsAnFollow( pSect
) ||
278 pSect
->IsAnFollow( pLayouter
->mpEndnoter
->GetSect() ) ) )
281 pLayouter
->CollectEndnote( pFootnote
);
287 bool SwLayouter::StartLoopControl( SwDoc
* pDoc
, SwPageFrame
const *pPage
)
290 if( !pDoc
->getIDocumentLayoutAccess().GetLayouter() )
291 pDoc
->getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
292 return !pDoc
->getIDocumentLayoutAccess().GetLayouter()->mpLooping
&&
293 pDoc
->getIDocumentLayoutAccess().GetLayouter()->StartLooping( pPage
);
297 // methods to manage text frames, which are moved forward by the positioning
298 // of its anchored objects
299 void SwLayouter::ClearMovedFwdFrames( const SwDoc
& _rDoc
)
301 if ( _rDoc
.getIDocumentLayoutAccess().GetLayouter() &&
302 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
)
304 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
->Clear();
308 void SwLayouter::InsertMovedFwdFrame( const SwDoc
& _rDoc
,
309 const SwTextFrame
& _rMovedFwdFrameByObjPos
,
310 const sal_uInt32 _nToPageNum
)
312 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter() )
314 const_cast<SwDoc
&>(_rDoc
).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
317 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
)
319 const_cast<SwDoc
&>(_rDoc
).getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
.reset(
320 new SwMovedFwdFramesByObjPos());
323 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
->Insert( _rMovedFwdFrameByObjPos
,
328 void SwLayouter::RemoveMovedFwdFrame( const SwDoc
& _rDoc
,
329 const SwTextFrame
& _rTextFrame
)
332 if ( SwLayouter::FrameMovedFwdByObjPos( _rDoc
, _rTextFrame
, nDummy
) )
334 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
->Remove( _rTextFrame
);
338 bool SwLayouter::FrameMovedFwdByObjPos( const SwDoc
& _rDoc
,
339 const SwTextFrame
& _rTextFrame
,
340 sal_uInt32
& _ornToPageNum
)
342 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter() )
347 else if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
)
354 return _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
->
355 FrameMovedFwdByObjPos( _rTextFrame
, _ornToPageNum
);
360 bool SwLayouter::DoesRowContainMovedFwdFrame( const SwDoc
& _rDoc
,
361 const SwRowFrame
& _rRowFrame
)
363 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter() )
367 else if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames
)
373 return _rDoc
.getIDocumentLayoutAccess().GetLayouter()->
374 mpMovedFwdFrames
->DoesRowContainMovedFwdFrame( _rRowFrame
);
379 void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc
& _rDoc
)
381 if ( _rDoc
.getIDocumentLayoutAccess().GetLayouter() &&
382 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
)
384 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
->Clear();
388 void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
390 SwAnchoredObject
& _rAnchoredObj
)
392 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter() )
394 const_cast<SwDoc
&>(_rDoc
).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
397 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
)
399 const_cast<SwDoc
&>(_rDoc
).getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
.reset(
400 new SwObjsMarkedAsTmpConsiderWrapInfluence());
403 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
->Insert( _rAnchoredObj
);
406 void SwLayouter::RemoveObjForTmpConsiderWrapInfluence(
408 SwAnchoredObject
& _rAnchoredObj
)
410 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter() )
413 if ( !_rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
)
416 _rDoc
.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl
->Remove( _rAnchoredObj
);
420 void LOOPING_LOUIE_LIGHT( bool bCondition
, const SwTextFrame
& rTextFrame
)
424 const SwDoc
& rDoc
= *rTextFrame
.GetAttrSet()->GetDoc();
425 if ( rDoc
.getIDocumentLayoutAccess().GetLayouter() )
427 const_cast<SwDoc
&>(rDoc
).getIDocumentLayoutAccess().GetLayouter()->LoopingLouieLight( rDoc
, rTextFrame
);
433 bool SwLayouter::MoveBwdSuppressed( const SwDoc
& p_rDoc
,
434 const SwFlowFrame
& p_rFlowFrame
,
435 const SwLayoutFrame
& p_rNewUpperFrame
)
437 bool bMoveBwdSuppressed( false );
439 if ( !p_rDoc
.getIDocumentLayoutAccess().GetLayouter() )
441 const_cast<SwDoc
&>(p_rDoc
).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
444 // create hash map key
445 tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo
;
446 aMoveBwdLayoutInfo
.mnFrameId
= p_rFlowFrame
.GetFrame().GetFrameId();
447 aMoveBwdLayoutInfo
.mnNewUpperPosX
= p_rNewUpperFrame
.getFrameArea().Pos().X();
448 aMoveBwdLayoutInfo
.mnNewUpperPosY
= p_rNewUpperFrame
.getFrameArea().Pos().Y();
449 aMoveBwdLayoutInfo
.mnNewUpperWidth
= p_rNewUpperFrame
.getFrameArea().Width();
450 aMoveBwdLayoutInfo
.mnNewUpperHeight
= p_rNewUpperFrame
.getFrameArea().Height();
451 SwRectFnSet
aRectFnSet(&p_rNewUpperFrame
);
452 const SwFrame
* pLastLower( p_rNewUpperFrame
.Lower() );
453 while ( pLastLower
&& pLastLower
->GetNext() )
455 pLastLower
= pLastLower
->GetNext();
457 aMoveBwdLayoutInfo
.mnFreeSpaceInNewUpper
=
459 ? aRectFnSet
.BottomDist( pLastLower
->getFrameArea(), aRectFnSet
.GetPrtBottom(p_rNewUpperFrame
) )
460 : aRectFnSet
.GetHeight(p_rNewUpperFrame
.getFrameArea());
462 // check for moving backward suppress threshold
463 const sal_uInt16 cMoveBwdCountSuppressThreshold
= 20;
464 if ( ++const_cast<SwDoc
&>(p_rDoc
).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo
[ aMoveBwdLayoutInfo
] >
465 cMoveBwdCountSuppressThreshold
)
467 bMoveBwdSuppressed
= true;
470 return bMoveBwdSuppressed
;
473 void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc
& _rDoc
)
475 if ( _rDoc
.getIDocumentLayoutAccess().GetLayouter() )
476 const_cast<SwDoc
&>(_rDoc
).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo
.clear();
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */