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 assert(pPage);
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#endif
188
189 // FME 2007-08-30 #i81146# new loop control
190 SAL_WARN("sw.layout", "Looping Louie: Stage " << (mnLoopControlStage + 1) << "!");
191
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() );
197
199 mnCount = 0;
200 }
201}
202
204{
205}
206
208{
209}
210
212{
213 if( !mpEndnoter )
214 mpEndnoter.reset(new SwEndnoter( this ));
215 mpEndnoter->CollectEndnotes( pSect );
216}
217
219{
220 return mpEndnoter->HasEndnotes();
221}
222
224{
225 mpEndnoter->CollectEndnote( pFootnote );
226}
227
229{
230 if( !mpEndnoter || mpEndnoter->GetSect() != pSect )
231 return;
232 mpEndnoter->InsertEndnotes();
233}
234
236{
237 assert(mpLooping);
238 mpLooping->Control( pPage );
239}
240
241void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTextFrame& rFrame )
242{
243 if ( mpLooping && mpLooping->IsLoopingLouieLight() )
244 {
245 SAL_WARN("sw.layout", "Looping Louie (Light): Fixating fractious frame");
247 }
248}
249
251{
252 if( mpLooping )
253 return false;
254 mpLooping.reset(new SwLooping( pPage ));
255 return true;
256}
257
259{
260 mpLooping.reset();
261}
262
264{
265 assert(pDoc && "No doc, no fun");
269}
270
271bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrame const * pSect, SwFootnoteFrame* pFootnote )
272{
274 return false;
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() ) ) )
279 {
280 if( pFootnote )
281 pLayouter->CollectEndnote( pFootnote );
282 return true;
283 }
284 return false;
285}
286
288{
289 assert(pDoc);
294}
295
296// #i28701#
297// methods to manage text frames, which are moved forward by the positioning
298// of its anchored objects
300{
301 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() &&
303 {
305 }
306}
307
309 const SwTextFrame& _rMovedFwdFrameByObjPos,
310 const sal_uInt32 _nToPageNum )
311{
312 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
313 {
314 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
315 }
316
318 {
319 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames.reset(
321 }
322
323 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Insert( _rMovedFwdFrameByObjPos,
324 _nToPageNum );
325}
326
327// #i40155#
329 const SwTextFrame& _rTextFrame )
330{
331 sal_uInt32 nDummy;
332 if ( SwLayouter::FrameMovedFwdByObjPos( _rDoc, _rTextFrame, nDummy ) )
333 {
334 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Remove( _rTextFrame );
335 }
336}
337
339 const SwTextFrame& _rTextFrame,
340 sal_uInt32& _ornToPageNum )
341{
342 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
343 {
344 _ornToPageNum = 0;
345 return false;
346 }
348 {
349 _ornToPageNum = 0;
350 return false;
351 }
352 else
353 {
355 FrameMovedFwdByObjPos( _rTextFrame, _ornToPageNum );
356 }
357}
358
359// #i26945#
361 const SwRowFrame& _rRowFrame )
362{
363 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
364 {
365 return false;
366 }
368 {
369 return false;
370 }
371 else
372 {
373 return _rDoc.getIDocumentLayoutAccess().GetLayouter()->
374 mpMovedFwdFrames->DoesRowContainMovedFwdFrame( _rRowFrame );
375 }
376}
377
378// #i35911#
380{
381 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() &&
383 {
385 }
386}
387
389 const SwDoc& _rDoc,
390 SwAnchoredObject& _rAnchoredObj )
391{
392 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
393 {
394 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
395 }
396
398 {
399 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl.reset(
401 }
402
403 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
404}
405
407 const SwDoc& _rDoc,
408 SwAnchoredObject& _rAnchoredObj )
409{
410 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
411 return;
412
414 return;
415
416 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Remove( _rAnchoredObj );
417}
418
419
420void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTextFrame& rTextFrame )
421{
422 if ( bCondition )
423 {
424 const SwDoc& rDoc = *rTextFrame.GetAttrSet()->GetDoc();
426 {
427 const_cast<SwDoc&>(rDoc).getIDocumentLayoutAccess().GetLayouter()->LoopingLouieLight( rDoc, rTextFrame );
428 }
429 }
430}
431
432// #i65250#
434 const SwFlowFrame& p_rFlowFrame,
435 const SwLayoutFrame& p_rNewUpperFrame )
436{
437 bool bMoveBwdSuppressed( false );
438
439 if ( !p_rDoc.getIDocumentLayoutAccess().GetLayouter() )
440 {
441 const_cast<SwDoc&>(p_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
442 }
443
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() )
454 {
455 pLastLower = pLastLower->GetNext();
456 }
457 aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
458 pLastLower
459 ? aRectFnSet.BottomDist( pLastLower->getFrameArea(), aRectFnSet.GetPrtBottom(p_rNewUpperFrame) )
460 : aRectFnSet.GetHeight(p_rNewUpperFrame.getFrameArea());
461
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 )
466 {
467 bMoveBwdSuppressed = true;
468 }
469
470 return bMoveBwdSuppressed;
471}
472
474{
476 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo.clear();
477}
478
479/* 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:204
Definition: doc.hxx:197
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:419
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:1969
Represents one footnote or endnote in the layout.
Definition: ftnfrm.hxx:84
const SwFootnoteFrame * GetFollow() const
Definition: ftnfrm.hxx:120
virtual void Cut() override
Definition: ftnfrm.cxx:543
const SwFootnoteFrame * GetMaster() const
Definition: ftnfrm.hxx:123
const SwTextFootnote * GetAttr() const
Definition: ftnfrm.hxx:126
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:2067
SwFrame * GetNext()
Definition: frame.hxx:682
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame,...
Definition: findfrm.cxx:762
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr)=0
SwLayoutFrame * GetUpper()
Definition: frame.hxx:684
bool IsFootnoteBossFrame() const
Definition: frame.hxx:1192
SwFrame * GetPrev()
Definition: frame.hxx:683
bool IsSctFrame() const
Definition: frame.hxx:1220
SwPageFrame * FindPageFrame()
Definition: frame.hxx:686
SwFootnoteBossFrame * FindFootnoteBossFrame(bool bFootnotes=false)
Definition: findfrm.cxx:491
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:390
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:131
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:360
void LoopingLouieLight(const SwDoc &rDoc, const SwTextFrame &rFrame)
Definition: layouter.cxx:241
static bool StartLoopControl(SwDoc *pDoc, SwPageFrame const *pPage)
Definition: layouter.cxx:287
static void InsertMovedFwdFrame(const SwDoc &_rDoc, const SwTextFrame &_rMovedFwdFrameByObjPos, const sal_uInt32 _nToPageNum)
Definition: layouter.cxx:308
std::unique_ptr< SwObjsMarkedAsTmpConsiderWrapInfluence > mpObjsTmpConsiderWrapInfl
Definition: layouter.hxx:53
static void ClearMovedFwdFrames(const SwDoc &_rDoc)
Definition: layouter.cxx:299
static void ClearMoveBwdLayoutInfo(const SwDoc &p_rDoc)
Definition: layouter.cxx:473
void InsertEndnotes(SwSectionFrame const *pSect)
Definition: layouter.cxx:228
static bool FrameMovedFwdByObjPos(const SwDoc &_rDoc, const SwTextFrame &_rTextFrame, sal_uInt32 &_ornToPageNum)
Definition: layouter.cxx:338
static void RemoveObjForTmpConsiderWrapInfluence(const SwDoc &_rDoc, SwAnchoredObject &_rAnchoredObj)
Definition: layouter.cxx:406
bool StartLooping(SwPageFrame const *pPage)
Definition: layouter.cxx:250
static void ClearObjsTmpConsiderWrapInfluence(const SwDoc &_rDoc)
Definition: layouter.cxx:379
std::unique_ptr< SwLooping > mpLooping
Definition: layouter.hxx:46
bool HasEndnotes() const
Definition: layouter.cxx:218
static void RemoveMovedFwdFrame(const SwDoc &_rDoc, const SwTextFrame &_rTextFrame)
Definition: layouter.cxx:328
void EndLoopControl()
Definition: layouter.cxx:258
std::unique_ptr< SwEndnoter > mpEndnoter
Definition: layouter.hxx:45
static void InsertObjForTmpConsiderWrapInfluence(const SwDoc &_rDoc, SwAnchoredObject &_rAnchoredObj)
Definition: layouter.cxx:388
static bool Collecting(SwDoc *pDoc, SwSectionFrame const *pSect, SwFootnoteFrame *pFootnote)
Definition: layouter.cxx:271
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:433
void LoopControl(SwPageFrame *pPage)
Definition: layouter.cxx:235
void CollectEndnotes_(SwSectionFrame *pSect)
Definition: layouter.cxx:211
void CollectEndnote(SwFootnoteFrame *pFootnote)
Definition: layouter.cxx:223
static void CollectEndnotes(SwDoc *pDoc, SwSectionFrame *pSect)
Definition: layouter.cxx:263
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:60
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:209
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1387
tools::Long BottomDist(const SwRect &rRect, tools::Long nPos) const
Definition: frame.hxx:1419
tools::Long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1415
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:1069
SwContentFrame * FindLastContent(SwFindMode nMode=SwFindMode::None)
Definition: sectfrm.cxx:935
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
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:420
#define SAL_WARN(area, stream)