LibreOffice Module sw (master) 1
layouter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <layouter.hxx>
22#include <doc.hxx>
23#include <sectfrm.hxx>
24#include <pagefrm.hxx>
25#include <ftnfrm.hxx>
26#include <txtfrm.hxx>
28
31#include <osl/diagnose.h>
32
33#define LOOP_DETECT 250
34
36{
37 sal_uInt16 mnMinPage;
38 sal_uInt16 mnMaxPage;
39 sal_uInt16 mnCount;
41public:
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; };
46};
47
49{
52 std::unique_ptr<SwFootnoteFrames> m_pEndArr;
53public:
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(); }
61};
62
64{
65 OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
66 if( !m_pSect )
67 m_pSect = pSct;
68 else if( pSct != m_pSect )
69 return;
71}
72
74{
75 if( m_pEndArr && m_pEndArr->end() != std::find( m_pEndArr->begin(), m_pEndArr->end(), pFootnote ) )
76 return;
77
78 if( pFootnote->GetUpper() )
79 {
80 // pFootnote is the master, he incorporates its follows
81 SwFootnoteFrame *pNxt = pFootnote->GetFollow();
82 while ( pNxt )
83 {
84 SwFrame *pCnt = pNxt->ContainsAny();
85 if ( pCnt )
86 {
87 do
88 { SwFrame *pNxtCnt = pCnt->GetNext();
89 pCnt->Cut();
90 pCnt->Paste( pFootnote );
91 pCnt = pNxtCnt;
92 } while ( pCnt );
93 }
94 else
95 {
96 OSL_ENSURE( pNxt->Lower() && pNxt->Lower()->IsSctFrame(),
97 "Endnote without content?" );
98 pNxt->Cut();
100 }
101 pNxt = pFootnote->GetFollow();
102 }
103 if( pFootnote->GetMaster() )
104 return;
105 pFootnote->Cut();
106 }
107 else if( m_pEndArr )
108 {
109 for (SwFootnoteFrame* pEndFootnote : *m_pEndArr)
110 {
111 if( pEndFootnote->GetAttr() == pFootnote->GetAttr() )
112 {
113 SwFrame::DestroyFrame(pFootnote);
114 return;
115 }
116 }
117 }
118 if( !m_pEndArr )
119 m_pEndArr.reset( new SwFootnoteFrames ); // deleted from the SwLayouter
120 m_pEndArr->push_back( pFootnote );
121}
122
124{
125 if( !m_pSect )
126 return;
127 if( !m_pEndArr || m_pEndArr->empty() )
128 {
129 m_pSect = nullptr;
130 return;
131 }
132 OSL_ENSURE( m_pSect->Lower() && m_pSect->Lower()->IsFootnoteBossFrame(),
133 "InsertEndnotes: Where's my column?" );
135 SwFootnoteBossFrame *pBoss = pRef ? pRef->FindFootnoteBossFrame()
136 : static_cast<SwFootnoteBossFrame*>(m_pSect->Lower());
137 pBoss->MoveFootnotes_( *m_pEndArr );
138 m_pEndArr.reset();
139 m_pSect = nullptr;
140}
141
143{
144 OSL_ENSURE( pPage, "Where's my page?" );
145 mnMinPage = pPage->GetPhyPageNum();
147 mnCount = 0;
149}
150
152{
153 while( pFrame )
154 {
156 pFrame = pFrame->GetNext();
157 }
158}
159
161{
162 if( !pPage )
163 return;
164 const sal_uInt16 nNew = pPage->GetPhyPageNum();
165 if (nNew > mnMaxPage)
166 mnMaxPage = nNew;
167 if (nNew < mnMinPage)
168 {
169 mnMinPage = nNew;
170 mnMaxPage = nNew;
171 mnCount = 0;
173 }
174 else if (nNew > mnMinPage + 2)
175 {
176 mnMinPage = nNew - 2;
177 mnMaxPage = nNew;
178 mnCount = 0;
180 }
181 else if (++mnCount > LOOP_DETECT)
182 {
183#if OSL_DEBUG_LEVEL > 1
184 static bool bNoLouie = false;
185 if( bNoLouie )
186 return;
187
188 // FME 2007-08-30 #i81146# new loop control
189 OSL_ENSURE( 0 != mnLoopControlStage, "Looping Louie: Stage 1!" );
190 OSL_ENSURE( 1 != mnLoopControlStage, "Looping Louie: Stage 2!!" );
191 OSL_ENSURE( 2 > mnLoopControlStage, "Looping Louie: Stage 3!!!" );
192#endif
193
194 Drastic( pPage->Lower() );
195 if (nNew > mnMinPage && pPage->GetPrev())
196 Drastic( static_cast<SwPageFrame*>(pPage->GetPrev())->Lower() );
197 if (nNew < mnMaxPage && pPage->GetNext())
198 Drastic( static_cast<SwPageFrame*>(pPage->GetNext())->Lower() );
199
201 mnCount = 0;
202 }
203}
204
206{
207}
208
210{
211}
212
214{
215 if( !mpEndnoter )
216 mpEndnoter.reset(new SwEndnoter( this ));
217 mpEndnoter->CollectEndnotes( pSect );
218}
219
221{
222 return mpEndnoter->HasEndnotes();
223}
224
226{
227 mpEndnoter->CollectEndnote( pFootnote );
228}
229
231{
232 if( !mpEndnoter || mpEndnoter->GetSect() != pSect )
233 return;
234 mpEndnoter->InsertEndnotes();
235}
236
238{
239 OSL_ENSURE( mpLooping, "Looping: Lost control" );
240 mpLooping->Control( pPage );
241}
242
243void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTextFrame& rFrame )
244{
245 if ( mpLooping && mpLooping->IsLoopingLouieLight() )
246 {
247#if OSL_DEBUG_LEVEL > 1
248 OSL_FAIL( "Looping Louie (Light): Fixating fractious frame" );
249#endif
251 }
252}
253
255{
256 if( mpLooping )
257 return false;
258 mpLooping.reset(new SwLooping( pPage ));
259 return true;
260}
261
263{
264 mpLooping.reset();
265}
266
268{
269 assert(pDoc && "No doc, no fun");
273}
274
275bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrame const * pSect, SwFootnoteFrame* pFootnote )
276{
278 return false;
279 SwLayouter *pLayouter = pDoc->getIDocumentLayoutAccess().GetLayouter();
280 if( pLayouter->mpEndnoter && pLayouter->mpEndnoter->GetSect() && pSect &&
281 ( pLayouter->mpEndnoter->GetSect()->IsAnFollow( pSect ) ||
282 pSect->IsAnFollow( pLayouter->mpEndnoter->GetSect() ) ) )
283 {
284 if( pFootnote )
285 pLayouter->CollectEndnote( pFootnote );
286 return true;
287 }
288 return false;
289}
290
292{
293 OSL_ENSURE( pDoc, "No doc, no fun" );
298}
299
300// #i28701#
301// methods to manage text frames, which are moved forward by the positioning
302// of its anchored objects
304{
305 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() &&
307 {
309 }
310}
311
313 const SwTextFrame& _rMovedFwdFrameByObjPos,
314 const sal_uInt32 _nToPageNum )
315{
316 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
317 {
318 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
319 }
320
322 {
323 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames.reset(
325 }
326
327 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Insert( _rMovedFwdFrameByObjPos,
328 _nToPageNum );
329}
330
331// #i40155#
333 const SwTextFrame& _rTextFrame )
334{
335 sal_uInt32 nDummy;
336 if ( SwLayouter::FrameMovedFwdByObjPos( _rDoc, _rTextFrame, nDummy ) )
337 {
338 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Remove( _rTextFrame );
339 }
340}
341
343 const SwTextFrame& _rTextFrame,
344 sal_uInt32& _ornToPageNum )
345{
346 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
347 {
348 _ornToPageNum = 0;
349 return false;
350 }
352 {
353 _ornToPageNum = 0;
354 return false;
355 }
356 else
357 {
359 FrameMovedFwdByObjPos( _rTextFrame, _ornToPageNum );
360 }
361}
362
363// #i26945#
365 const SwRowFrame& _rRowFrame )
366{
367 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
368 {
369 return false;
370 }
372 {
373 return false;
374 }
375 else
376 {
377 return _rDoc.getIDocumentLayoutAccess().GetLayouter()->
378 mpMovedFwdFrames->DoesRowContainMovedFwdFrame( _rRowFrame );
379 }
380}
381
382// #i35911#
384{
385 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() &&
387 {
389 }
390}
391
393 const SwDoc& _rDoc,
394 SwAnchoredObject& _rAnchoredObj )
395{
396 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
397 {
398 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
399 }
400
402 {
403 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl.reset(
405 }
406
407 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
408}
409
411 const SwDoc& _rDoc,
412 SwAnchoredObject& _rAnchoredObj )
413{
414 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
415 return;
416
418 return;
419
420 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Remove( _rAnchoredObj );
421}
422
423
424void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTextFrame& rTextFrame )
425{
426 if ( bCondition )
427 {
428 const SwDoc& rDoc = *rTextFrame.GetAttrSet()->GetDoc();
430 {
431 const_cast<SwDoc&>(rDoc).getIDocumentLayoutAccess().GetLayouter()->LoopingLouieLight( rDoc, rTextFrame );
432 }
433 }
434}
435
436// #i65250#
438 const SwFlowFrame& p_rFlowFrame,
439 const SwLayoutFrame& p_rNewUpperFrame )
440{
441 bool bMoveBwdSuppressed( false );
442
443 if ( !p_rDoc.getIDocumentLayoutAccess().GetLayouter() )
444 {
445 const_cast<SwDoc&>(p_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
446 }
447
448 // create hash map key
449 tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
450 aMoveBwdLayoutInfo.mnFrameId = p_rFlowFrame.GetFrame().GetFrameId();
451 aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrame.getFrameArea().Pos().X();
452 aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrame.getFrameArea().Pos().Y();
453 aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrame.getFrameArea().Width();
454 aMoveBwdLayoutInfo.mnNewUpperHeight = p_rNewUpperFrame.getFrameArea().Height();
455 SwRectFnSet aRectFnSet(&p_rNewUpperFrame);
456 const SwFrame* pLastLower( p_rNewUpperFrame.Lower() );
457 while ( pLastLower && pLastLower->GetNext() )
458 {
459 pLastLower = pLastLower->GetNext();
460 }
461 aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
462 pLastLower
463 ? aRectFnSet.BottomDist( pLastLower->getFrameArea(), aRectFnSet.GetPrtBottom(p_rNewUpperFrame) )
464 : aRectFnSet.GetHeight(p_rNewUpperFrame.getFrameArea());
465
466 // check for moving backward suppress threshold
467 const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
468 if ( ++const_cast<SwDoc&>(p_rDoc).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
469 cMoveBwdCountSuppressThreshold )
470 {
471 bMoveBwdSuppressed = true;
472 }
473
474 return bMoveBwdSuppressed;
475}
476
478{
480 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo.clear();
481}
482
483/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void SetLayouter(SwLayouter *pNew)=0
virtual SwLayouter * GetLayouter()=0
wrapper class for the positioning of Writer fly frames and drawing objects
const SwDoc * GetDoc() const
Definition: swatrset.hxx:197
Definition: doc.hxx:194
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:411
SwLayouter * m_pMaster
Definition: layouter.cxx:50
void CollectEndnote(SwFootnoteFrame *pFootnote)
Definition: layouter.cxx:73
SwSectionFrame * m_pSect
Definition: layouter.cxx:51
std::unique_ptr< SwFootnoteFrames > m_pEndArr
Definition: layouter.cxx:52
void CollectEndnotes(SwSectionFrame *pSct)
Definition: layouter.cxx:63
void InsertEndnotes()
Definition: layouter.cxx:123
const SwSectionFrame * GetSect() const
Definition: layouter.cxx:58
bool HasEndnotes() const
Definition: layouter.cxx:60
SwEndnoter(SwLayouter *pLay)
Definition: layouter.cxx:54
void MoveFootnotes_(SwFootnoteFrames &rFootnoteArr, bool bCalc=false)
Definition: ftnfrm.cxx:1967
const SwFootnoteFrame * GetFollow() const
Definition: ftnfrm.hxx:116
virtual void Cut() override
Definition: ftnfrm.cxx:541
const SwFootnoteFrame * GetMaster() const
Definition: ftnfrm.hxx:119
const SwTextFootnote * GetAttr() const
Definition: ftnfrm.hxx:122
const SwRect & getFrameArea() const
Definition: frame.hxx:179
Base class of the Writer layout elements.
Definition: frame.hxx:315
virtual void Cut()=0
void ValidateThisAndAllLowers(const sal_uInt16 nStage)
Definition: wsfrm.cxx:2061
SwFrame * GetNext()
Definition: frame.hxx:676
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame,...
Definition: findfrm.cxx:731
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr)=0
SwLayoutFrame * GetUpper()
Definition: frame.hxx:678
bool IsFootnoteBossFrame() const
Definition: frame.hxx:1186
SwFrame * GetPrev()
Definition: frame.hxx:677
bool IsSctFrame() const
Definition: frame.hxx:1214
SwPageFrame * FindPageFrame()
Definition: frame.hxx:680
SwFootnoteBossFrame * FindFootnoteBossFrame(bool bFootnotes=false)
Definition: findfrm.cxx:460
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:388
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame.
Definition: layfrm.hxx:36
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method <ContainsAny()> doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:129
const SwFrame * Lower() const
Definition: layfrm.hxx:101
std::unordered_map< tMoveBwdLayoutInfoKey, sal_uInt16, fMoveBwdLayoutInfoKeyHash, fMoveBwdLayoutInfoKeyEq > maMoveBwdLayoutInfo
Definition: layouter.hxx:95
static bool DoesRowContainMovedFwdFrame(const SwDoc &_rDoc, const SwRowFrame &_rRowFrame)
Definition: layouter.cxx:364
void LoopingLouieLight(const SwDoc &rDoc, const SwTextFrame &rFrame)
Definition: layouter.cxx:243
static bool StartLoopControl(SwDoc *pDoc, SwPageFrame const *pPage)
Definition: layouter.cxx:291
static void InsertMovedFwdFrame(const SwDoc &_rDoc, const SwTextFrame &_rMovedFwdFrameByObjPos, const sal_uInt32 _nToPageNum)
Definition: layouter.cxx:312
std::unique_ptr< SwObjsMarkedAsTmpConsiderWrapInfluence > mpObjsTmpConsiderWrapInfl
Definition: layouter.hxx:53
static void ClearMovedFwdFrames(const SwDoc &_rDoc)
Definition: layouter.cxx:303
static void ClearMoveBwdLayoutInfo(const SwDoc &p_rDoc)
Definition: layouter.cxx:477
void InsertEndnotes(SwSectionFrame const *pSect)
Definition: layouter.cxx:230
static bool FrameMovedFwdByObjPos(const SwDoc &_rDoc, const SwTextFrame &_rTextFrame, sal_uInt32 &_ornToPageNum)
Definition: layouter.cxx:342
static void RemoveObjForTmpConsiderWrapInfluence(const SwDoc &_rDoc, SwAnchoredObject &_rAnchoredObj)
Definition: layouter.cxx:410
bool StartLooping(SwPageFrame const *pPage)
Definition: layouter.cxx:254
static void ClearObjsTmpConsiderWrapInfluence(const SwDoc &_rDoc)
Definition: layouter.cxx:383
std::unique_ptr< SwLooping > mpLooping
Definition: layouter.hxx:46
bool HasEndnotes() const
Definition: layouter.cxx:220
static void RemoveMovedFwdFrame(const SwDoc &_rDoc, const SwTextFrame &_rTextFrame)
Definition: layouter.cxx:332
void EndLoopControl()
Definition: layouter.cxx:262
std::unique_ptr< SwEndnoter > mpEndnoter
Definition: layouter.hxx:45
static void InsertObjForTmpConsiderWrapInfluence(const SwDoc &_rDoc, SwAnchoredObject &_rAnchoredObj)
Definition: layouter.cxx:392
static bool Collecting(SwDoc *pDoc, SwSectionFrame const *pSect, SwFootnoteFrame *pFootnote)
Definition: layouter.cxx:275
std::unique_ptr< SwMovedFwdFramesByObjPos > mpMovedFwdFrames
Definition: layouter.hxx:51
static bool MoveBwdSuppressed(const SwDoc &p_rDoc, const SwFlowFrame &p_rFlowFrame, const SwLayoutFrame &p_rNewUpperFrame)
Definition: layouter.cxx:437
void LoopControl(SwPageFrame *pPage)
Definition: layouter.cxx:237
void CollectEndnotes_(SwSectionFrame *pSect)
Definition: layouter.cxx:213
void CollectEndnote(SwFootnoteFrame *pFootnote)
Definition: layouter.cxx:225
static void CollectEndnotes(SwDoc *pDoc, SwSectionFrame *pSect)
Definition: layouter.cxx:267
sal_uInt16 mnMinPage
Definition: layouter.cxx:37
sal_uInt16 mnCount
Definition: layouter.cxx:39
SwLooping(SwPageFrame const *pPage)
Definition: layouter.cxx:142
void Drastic(SwFrame *pFrame)
Definition: layouter.cxx:151
void Control(SwPageFrame *pPage)
Definition: layouter.cxx:160
bool IsLoopingLouieLight() const
Definition: layouter.cxx:45
sal_uInt16 mnMaxPage
Definition: layouter.cxx:38
sal_uInt16 mnLoopControlStage
Definition: layouter.cxx:40
A page of the document layout.
Definition: pagefrm.hxx:58
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:204
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1381
tools::Long BottomDist(const SwRect &rRect, tools::Long nPos) const
Definition: frame.hxx:1413
tools::Long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1409
void Height(tools::Long nNew)
Definition: swrect.hxx:193
void Pos(const Point &rNew)
Definition: swrect.hxx:171
void Width(tools::Long nNew)
Definition: swrect.hxx:189
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:29
void CollectEndnotes(SwLayouter *pLayouter)
Definition: sectfrm.cxx:1052
SwContentFrame * FindLastContent(SwFindMode nMode=SwFindMode::None)
Definition: sectfrm.cxx:918
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:165
std::vector< SwFootnoteFrame * > SwFootnoteFrames
Definition: ftnboss.hxx:47
#define LOOP_DETECT
Definition: layouter.cxx:33
void LOOPING_LOUIE_LIGHT(bool bCondition, const SwTextFrame &rTextFrame)
Definition: layouter.cxx:424