Line data Source code
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 <objectformattertxtfrm.hxx>
21 : #include <sortedobjs.hxx>
22 : #include <flyfrms.hxx>
23 : #include <txtfrm.hxx>
24 : #include <pagefrm.hxx>
25 : #include <rowfrm.hxx>
26 : #include <layouter.hxx>
27 : #include <fmtanchr.hxx>
28 : #include <fmtwrapinfluenceonobjpos.hxx>
29 : #include <fmtfollowtextflow.hxx>
30 : #include <layact.hxx>
31 :
32 : using namespace ::com::sun::star;
33 :
34 : // little helper class to forbid follow formatting for the given text frame
35 : class SwForbidFollowFormat
36 : {
37 : private:
38 : SwTxtFrm& mrTxtFrm;
39 : const bool bOldFollowFormatAllowed;
40 :
41 : public:
42 1106 : SwForbidFollowFormat( SwTxtFrm& _rTxtFrm )
43 : : mrTxtFrm( _rTxtFrm ),
44 1106 : bOldFollowFormatAllowed( _rTxtFrm.FollowFormatAllowed() )
45 : {
46 1106 : mrTxtFrm.ForbidFollowFormat();
47 1106 : }
48 :
49 1106 : ~SwForbidFollowFormat()
50 : {
51 1106 : if ( bOldFollowFormatAllowed )
52 : {
53 1106 : mrTxtFrm.AllowFollowFormat();
54 : }
55 1106 : }
56 : };
57 :
58 15410 : SwObjectFormatterTxtFrm::SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
59 : const SwPageFrm& _rPageFrm,
60 : SwTxtFrm* _pMasterAnchorTxtFrm,
61 : SwLayAction* _pLayAction )
62 : : SwObjectFormatter( _rPageFrm, _pLayAction, true ),
63 : mrAnchorTxtFrm( _rAnchorTxtFrm ),
64 15410 : mpMasterAnchorTxtFrm( _pMasterAnchorTxtFrm )
65 : {
66 15410 : }
67 :
68 30820 : SwObjectFormatterTxtFrm::~SwObjectFormatterTxtFrm()
69 : {
70 30820 : }
71 :
72 265841 : SwObjectFormatterTxtFrm* SwObjectFormatterTxtFrm::CreateObjFormatter(
73 : SwTxtFrm& _rAnchorTxtFrm,
74 : const SwPageFrm& _rPageFrm,
75 : SwLayAction* _pLayAction )
76 : {
77 265841 : SwObjectFormatterTxtFrm* pObjFormatter = 0L;
78 :
79 : // determine 'master' of <_rAnchorTxtFrm>, if anchor frame is a follow text frame.
80 265841 : SwTxtFrm* pMasterOfAnchorFrm = 0L;
81 265841 : if ( _rAnchorTxtFrm.IsFollow() )
82 : {
83 2416 : pMasterOfAnchorFrm = _rAnchorTxtFrm.FindMaster();
84 8584 : while ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->IsFollow() )
85 : {
86 3752 : pMasterOfAnchorFrm = pMasterOfAnchorFrm->FindMaster();
87 : }
88 : }
89 :
90 : // create object formatter, if floating screen objects are registered
91 : // at anchor frame (or at 'master' anchor frame)
92 281251 : if ( _rAnchorTxtFrm.GetDrawObjs() ||
93 2404 : ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->GetDrawObjs() ) )
94 : {
95 : pObjFormatter =
96 : new SwObjectFormatterTxtFrm( _rAnchorTxtFrm, _rPageFrm,
97 15410 : pMasterOfAnchorFrm, _pLayAction );
98 : }
99 :
100 265841 : return pObjFormatter;
101 : }
102 :
103 44816 : SwFrm& SwObjectFormatterTxtFrm::GetAnchorFrm()
104 : {
105 44816 : return mrAnchorTxtFrm;
106 : }
107 :
108 : // #i40147# - add parameter <_bCheckForMovedFwd>.
109 26374 : bool SwObjectFormatterTxtFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
110 : const bool _bCheckForMovedFwd )
111 : {
112 : // check, if only as-character anchored object have to be formatted, and
113 : // check the anchor type
114 26374 : if ( FormatOnlyAsCharAnchored() &&
115 0 : !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
116 : {
117 0 : return true;
118 : }
119 :
120 : // consider, if the layout action has to be
121 : // restarted due to a delete of a page frame.
122 26374 : if ( GetLayAction() && GetLayAction()->IsAgain() )
123 : {
124 0 : return false;
125 : }
126 :
127 26374 : bool bSuccess( true );
128 :
129 26374 : if ( _rAnchoredObj.IsFormatPossible() )
130 : {
131 26374 : _rAnchoredObj.SetRestartLayoutProcess( false );
132 :
133 26374 : _FormatObj( _rAnchoredObj );
134 : // consider, if the layout action has to be
135 : // restarted due to a delete of a page frame.
136 26374 : if ( GetLayAction() && GetLayAction()->IsAgain() )
137 : {
138 0 : return false;
139 : }
140 :
141 : // check, if layout process has to be restarted.
142 : // if yes, perform needed invalidations.
143 :
144 : // no restart of layout process,
145 : // if anchored object is anchored inside a Writer fly frame,
146 : // its position is already locked, and it follows the text flow.
147 : const bool bRestart =
148 28098 : _rAnchoredObj.RestartLayoutProcess() &&
149 862 : !( _rAnchoredObj.PositionLocked() &&
150 0 : _rAnchoredObj.GetAnchorFrm()->IsInFly() &&
151 26374 : _rAnchoredObj.GetFrmFmt().GetFollowTextFlow().GetValue() );
152 26374 : if ( bRestart )
153 : {
154 862 : bSuccess = false;
155 862 : _InvalidatePrevObjs( _rAnchoredObj );
156 862 : _InvalidateFollowObjs( _rAnchoredObj, true );
157 : }
158 :
159 : // format anchor text frame, if wrapping style influence of the object
160 : // has to be considered and it's <NONE_SUCCESSIVE_POSITIONED>
161 : // #i3317# - consider also anchored objects, whose
162 : // wrapping style influence is temporarly considered.
163 : // #i40147# - consider also anchored objects, for
164 : // whose the check of a moved forward anchor frame is requested.
165 : // revise decision made for i3317:
166 : // anchored objects, whose wrapping style influence is temporarly considered,
167 : // have to be considered in method <SwObjectFormatterTxtFrm::DoFormatObjs()>
168 51886 : if ( bSuccess &&
169 28918 : _rAnchoredObj.ConsiderObjWrapInfluenceOnObjPos() &&
170 2514 : ( _bCheckForMovedFwd ||
171 2514 : _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
172 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
173 2514 : GetWrapInfluenceOnObjPos( true ) ==
174 : // #i35017# - constant name has changed
175 : text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) )
176 : {
177 : // #i26945# - check conditions for move forward of
178 : // anchor text frame
179 : // determine, if anchor text frame has previous frame
180 20 : const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
181 :
182 : // #i40141# - use new method - it also formats the
183 : // section the anchor frame is in.
184 20 : _FormatAnchorFrmForCheckMoveFwd();
185 :
186 : // #i35911#
187 20 : if ( _rAnchoredObj.HasClearedEnvironment() )
188 : {
189 0 : _rAnchoredObj.SetClearedEnvironment( true );
190 : // #i44049# - consider, that anchor frame
191 : // could already been marked to move forward.
192 0 : SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
193 0 : if ( pAnchorPageFrm != _rAnchoredObj.GetPageFrm() )
194 : {
195 0 : bool bInsert( true );
196 0 : sal_uInt32 nToPageNum( 0L );
197 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
198 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
199 0 : rDoc, mrAnchorTxtFrm, nToPageNum ) )
200 : {
201 0 : if ( nToPageNum < pAnchorPageFrm->GetPhyPageNum() )
202 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
203 : else
204 0 : bInsert = false;
205 : }
206 0 : if ( bInsert )
207 : {
208 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
209 0 : pAnchorPageFrm->GetPhyPageNum() );
210 0 : mrAnchorTxtFrm.InvalidatePos();
211 0 : bSuccess = false;
212 0 : _InvalidatePrevObjs( _rAnchoredObj );
213 0 : _InvalidateFollowObjs( _rAnchoredObj, true );
214 : }
215 : else
216 : {
217 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
218 : }
219 : }
220 : }
221 20 : else if ( !mrAnchorTxtFrm.IsFollow() && bDoesAnchorHadPrev )
222 : {
223 : // index of anchored object in collection of page numbers and
224 : // anchor types
225 16 : sal_uInt32 nIdx( CountOfCollected() );
226 : OSL_ENSURE( nIdx > 0,
227 : "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchored object not collected!?" );
228 16 : --nIdx;
229 :
230 16 : sal_uInt32 nToPageNum( 0L );
231 : // #i43913#
232 16 : bool bDummy( false );
233 : // #i58182# - consider new method signature
234 16 : if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( nIdx ),
235 : GetPgNumOfCollected( nIdx ),
236 16 : IsCollectedAnchoredAtMaster( nIdx ),
237 16 : nToPageNum, bDummy ) )
238 : {
239 : // #i49987# - consider, that anchor frame
240 : // could already been marked to move forward.
241 0 : bool bInsert( true );
242 0 : sal_uInt32 nMovedFwdToPageNum( 0L );
243 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
244 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
245 0 : rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
246 : {
247 0 : if ( nMovedFwdToPageNum < nToPageNum )
248 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
249 : else
250 0 : bInsert = false;
251 : }
252 0 : if ( bInsert )
253 : {
254 : // Indicate that anchor text frame has to move forward and
255 : // invalidate its position to force a re-format.
256 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
257 0 : nToPageNum );
258 0 : mrAnchorTxtFrm.InvalidatePos();
259 :
260 : // Indicate restart of the layout process
261 0 : bSuccess = false;
262 :
263 : // If needed, invalidate previous objects anchored at same anchor
264 : // text frame.
265 0 : _InvalidatePrevObjs( _rAnchoredObj );
266 :
267 : // Invalidate object and following objects for the restart of the
268 : // layout process
269 0 : _InvalidateFollowObjs( _rAnchoredObj, true );
270 : }
271 : else
272 : {
273 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
274 : }
275 : }
276 : }
277 : // i40155# - mark anchor frame not to wrap around
278 : // objects under the condition, that its follow contains all its text.
279 12 : else if ( !mrAnchorTxtFrm.IsFollow() &&
280 4 : mrAnchorTxtFrm.GetFollow() &&
281 0 : mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
282 : {
283 : SwLayouter::RemoveMovedFwdFrm(
284 0 : *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
285 0 : mrAnchorTxtFrm );
286 : }
287 : }
288 : }
289 :
290 26374 : return bSuccess;
291 : }
292 :
293 13992 : bool SwObjectFormatterTxtFrm::DoFormatObjs()
294 : {
295 13992 : if ( !mrAnchorTxtFrm.IsValid() )
296 : {
297 0 : if ( GetLayAction() &&
298 0 : mrAnchorTxtFrm.FindPageFrm() != &GetPageFrm() )
299 : {
300 : // notify layout action, thus is can restart the layout process on
301 : // a previous page.
302 0 : GetLayAction()->SetAgain();
303 : }
304 : else
305 : {
306 : // the anchor text frame has to be valid, thus assert.
307 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs()> called for invalidate anchor text frame." );
308 : }
309 :
310 0 : return false;
311 : }
312 :
313 13992 : bool bSuccess( true );
314 :
315 13992 : if ( mrAnchorTxtFrm.IsFollow() )
316 : {
317 : // Only floating screen objects anchored as-character are directly
318 : // registered at a follow text frame. The other floating screen objects
319 : // are registered at the 'master' anchor text frame.
320 : // Thus, format the other floating screen objects through the 'master'
321 : // anchor text frame
322 : OSL_ENSURE( mpMasterAnchorTxtFrm,
323 : "SwObjectFormatterTxtFrm::DoFormatObjs() - missing 'master' anchor text frame" );
324 26 : bSuccess = _FormatObjsAtFrm( mpMasterAnchorTxtFrm );
325 :
326 26 : if ( bSuccess )
327 : {
328 : // format of as-character anchored floating screen objects - no failure
329 : // excepted on the format of these objects.
330 26 : bSuccess = _FormatObjsAtFrm();
331 : }
332 : }
333 : else
334 : {
335 13966 : bSuccess = _FormatObjsAtFrm();
336 : }
337 :
338 : // consider anchored objects, whose wrapping style influence are temporarly
339 : // considered.
340 38554 : if ( bSuccess &&
341 14864 : ( ConsiderWrapOnObjPos() ||
342 3438 : ( !mrAnchorTxtFrm.IsFollow() &&
343 1716 : _AtLeastOneObjIsTmpConsiderWrapInfluence() ) ) )
344 : {
345 11420 : const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
346 :
347 : // Format anchor text frame after its objects are formatted.
348 : // Note: The format of the anchor frame also formats the invalid
349 : // previous frames of the anchor frame. The format of the previous
350 : // frames is needed to get a correct result of format of the
351 : // anchor frame for the following check for moved forward anchors
352 : // #i40141# - use new method - it also formats the
353 : // section the anchor frame is in.
354 11420 : _FormatAnchorFrmForCheckMoveFwd();
355 :
356 11420 : sal_uInt32 nToPageNum( 0L );
357 : // #i43913#
358 11420 : bool bInFollow( false );
359 11420 : SwAnchoredObject* pObj = 0L;
360 11420 : if ( !mrAnchorTxtFrm.IsFollow() )
361 : {
362 : pObj = _GetFirstObjWithMovedFwdAnchor(
363 : // #i35017# - constant name has changed
364 : text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
365 11400 : nToPageNum, bInFollow );
366 : }
367 : // #i35911#
368 11420 : if ( pObj && pObj->HasClearedEnvironment() )
369 : {
370 8 : pObj->SetClearedEnvironment( true );
371 : // #i44049# - consider, that anchor frame
372 : // could already been marked to move forward.
373 8 : SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
374 : // #i43913# - consider, that anchor frame
375 : // is a follow or is in a follow row, which will move forward.
376 8 : if ( pAnchorPageFrm != pObj->GetPageFrm() ||
377 : bInFollow )
378 : {
379 0 : bool bInsert( true );
380 0 : sal_uInt32 nTmpToPageNum( 0L );
381 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
382 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
383 0 : rDoc, mrAnchorTxtFrm, nTmpToPageNum ) )
384 : {
385 0 : if ( nTmpToPageNum < pAnchorPageFrm->GetPhyPageNum() )
386 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
387 : else
388 0 : bInsert = false;
389 : }
390 0 : if ( bInsert )
391 : {
392 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
393 0 : pAnchorPageFrm->GetPhyPageNum() );
394 0 : mrAnchorTxtFrm.InvalidatePos();
395 0 : bSuccess = false;
396 0 : _InvalidatePrevObjs( *pObj );
397 0 : _InvalidateFollowObjs( *pObj, true );
398 : }
399 : else
400 : {
401 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
402 : }
403 : }
404 : }
405 11412 : else if ( pObj && bDoesAnchorHadPrev )
406 : {
407 : // Object found, whose anchor is moved forward
408 :
409 : // #i49987# - consider, that anchor frame
410 : // could already been marked to move forward.
411 0 : bool bInsert( true );
412 0 : sal_uInt32 nMovedFwdToPageNum( 0L );
413 0 : const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
414 0 : if ( SwLayouter::FrmMovedFwdByObjPos(
415 0 : rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
416 : {
417 0 : if ( nMovedFwdToPageNum < nToPageNum )
418 0 : SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
419 : else
420 0 : bInsert = false;
421 : }
422 0 : if ( bInsert )
423 : {
424 : // Indicate that anchor text frame has to move forward and
425 : // invalidate its position to force a re-format.
426 0 : SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm, nToPageNum );
427 0 : mrAnchorTxtFrm.InvalidatePos();
428 :
429 : // Indicate restart of the layout process
430 0 : bSuccess = false;
431 :
432 : // If needed, invalidate previous objects anchored at same anchor
433 : // text frame.
434 0 : _InvalidatePrevObjs( *pObj );
435 :
436 : // Invalidate object and following objects for the restart of the
437 : // layout process
438 0 : _InvalidateFollowObjs( *pObj, true );
439 : }
440 : else
441 : {
442 : OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
443 0 : }
444 : }
445 : // #i40155# - mark anchor frame not to wrap around
446 : // objects under the condition, that its follow contains all its text.
447 34216 : else if ( !mrAnchorTxtFrm.IsFollow() &&
448 11440 : mrAnchorTxtFrm.GetFollow() &&
449 28 : mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
450 : {
451 : SwLayouter::RemoveMovedFwdFrm(
452 12 : *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
453 24 : mrAnchorTxtFrm );
454 : }
455 : }
456 :
457 13992 : return bSuccess;
458 : }
459 :
460 862 : void SwObjectFormatterTxtFrm::_InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj )
461 : {
462 : // invalidate all previous objects, whose wrapping influence on the object
463 : // positioning is <NONE_CONCURRENT_POSIITIONED>.
464 : // Note: list of objects at anchor frame is sorted by this property.
465 1724 : if ( _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
466 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
467 862 : GetWrapInfluenceOnObjPos( true ) ==
468 : // #i35017# - constant name has changed
469 : text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
470 : {
471 852 : const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
472 852 : if ( pObjs )
473 : {
474 : // determine start index
475 852 : size_t i = pObjs->ListPosOf( _rAnchoredObj );
476 1998 : while (i > 0)
477 : {
478 294 : --i;
479 294 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
480 588 : if ( pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
481 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
482 294 : GetWrapInfluenceOnObjPos( true ) ==
483 : // #i35017# - constant name has changed
484 : text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
485 : {
486 294 : pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
487 : }
488 : }
489 : }
490 : }
491 862 : }
492 :
493 862 : void SwObjectFormatterTxtFrm::_InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
494 : const bool _bInclObj )
495 : {
496 862 : if ( _bInclObj )
497 : {
498 862 : _rAnchoredObj.InvalidateObjPosForConsiderWrapInfluence( true );
499 : }
500 :
501 862 : const SwSortedObjs* pObjs = GetPageFrm().GetSortedObjs();
502 862 : if ( pObjs )
503 : {
504 : // determine start index
505 1258 : for ( size_t i = pObjs->ListPosOf( _rAnchoredObj ) + 1; i < pObjs->size(); ++i )
506 : {
507 396 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
508 396 : pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
509 : }
510 : }
511 862 : }
512 :
513 11400 : SwAnchoredObject* SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(
514 : const sal_Int16 _nWrapInfluenceOnPosition,
515 : sal_uInt32& _noToPageNum,
516 : bool& _boInFollow )
517 : {
518 : // #i35017# - constant names have changed
519 : OSL_ENSURE( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
520 : _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
521 : "<SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(..)> - invalid value for parameter <_nWrapInfluenceOnPosition>" );
522 :
523 11400 : SwAnchoredObject* pRetAnchoredObj = 0L;
524 :
525 11400 : sal_uInt32 i = 0L;
526 32880 : for ( ; i < CountOfCollected(); ++i )
527 : {
528 21488 : SwAnchoredObject* pAnchoredObj = GetCollectedObj(i);
529 23864 : if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() &&
530 2376 : pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
531 : // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
532 2376 : GetWrapInfluenceOnObjPos( true ) == _nWrapInfluenceOnPosition )
533 : {
534 : // #i26945# - use new method <_CheckMovedFwdCondition(..)>
535 : // #i43913#
536 : // #i58182# - consider new method signature
537 2366 : if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( i ),
538 : GetPgNumOfCollected( i ),
539 2366 : IsCollectedAnchoredAtMaster( i ),
540 2366 : _noToPageNum, _boInFollow ) )
541 : {
542 8 : pRetAnchoredObj = pAnchoredObj;
543 8 : break;
544 : }
545 : }
546 : }
547 :
548 11400 : return pRetAnchoredObj;
549 : }
550 :
551 : // #i58182#
552 : // - replace private method by corresponding static public method
553 5894 : bool SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
554 : SwAnchoredObject& _rAnchoredObj,
555 : const sal_uInt32 _nFromPageNum,
556 : const bool _bAnchoredAtMasterBeforeFormatAnchor,
557 : sal_uInt32& _noToPageNum,
558 : bool& _boInFollow )
559 : {
560 5894 : bool bAnchorIsMovedForward( false );
561 :
562 5894 : SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
563 5894 : if ( pPageFrmOfAnchor )
564 : {
565 5894 : const sal_uInt32 nPageNum = pPageFrmOfAnchor->GetPhyPageNum();
566 5894 : if ( nPageNum > _nFromPageNum )
567 : {
568 8 : _noToPageNum = nPageNum;
569 : // Handling of special case:
570 : // If anchor frame is move forward into a follow flow row,
571 : // <_noToPageNum> is set to <_nFromPageNum + 1>, because it is
572 : // possible that the anchor page frame isn't valid, because the
573 : // page distance between master row and follow flow row is greater
574 : // than 1.
575 8 : if ( _noToPageNum > (_nFromPageNum + 1) )
576 : {
577 0 : SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
578 0 : if ( pAnchorFrm->IsInTab() &&
579 0 : pAnchorFrm->IsInFollowFlowRow() )
580 : {
581 0 : _noToPageNum = _nFromPageNum + 1;
582 : }
583 : }
584 8 : bAnchorIsMovedForward = true;
585 : }
586 : }
587 : // #i26945# - check, if an at-paragraph|at-character
588 : // anchored object is now anchored at a follow text frame, which will be
589 : // on the next page. Also check, if an at-character anchored object
590 : // is now anchored at a text frame, which is in a follow flow row,
591 : // which will be on the next page.
592 17674 : if ( !bAnchorIsMovedForward &&
593 17666 : _bAnchoredAtMasterBeforeFormatAnchor &&
594 10642 : ((_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR) ||
595 4756 : (_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_PARA)))
596 : {
597 5886 : SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
598 : OSL_ENSURE( pAnchorFrm->IsTxtFrm(),
599 : "<SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..) - wrong type of anchor frame>" );
600 5886 : SwTxtFrm* pAnchorTxtFrm = static_cast<SwTxtFrm*>(pAnchorFrm);
601 5886 : bool bCheck( false );
602 5886 : if ( pAnchorTxtFrm->IsFollow() )
603 : {
604 0 : bCheck = true;
605 : }
606 5886 : else if( pAnchorTxtFrm->IsInTab() )
607 : {
608 60 : const SwRowFrm* pMasterRow = pAnchorTxtFrm->IsInFollowFlowRow();
609 60 : if ( pMasterRow &&
610 0 : pMasterRow->FindPageFrm() == pPageFrmOfAnchor )
611 : {
612 0 : bCheck = true;
613 : }
614 : }
615 5886 : if ( bCheck )
616 : {
617 : // check, if found text frame will be on the next page
618 : // by checking, if it's in a column, which has no next.
619 0 : SwFrm* pColFrm = pAnchorTxtFrm->FindColFrm();
620 0 : while ( pColFrm && !pColFrm->GetNext() )
621 : {
622 0 : pColFrm = pColFrm->FindColFrm();
623 : }
624 0 : if ( !pColFrm || !pColFrm->GetNext() )
625 : {
626 0 : _noToPageNum = _nFromPageNum + 1;
627 0 : bAnchorIsMovedForward = true;
628 : // #i43913#
629 0 : _boInFollow = true;
630 : }
631 : }
632 : }
633 :
634 5894 : return bAnchorIsMovedForward;
635 : }
636 :
637 : // #i40140# - helper method to format layout frames used by
638 : // method <SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()>
639 : // #i44049# - format till a certain lower frame, if provided.
640 346 : static void lcl_FormatCntntOfLayoutFrm( SwLayoutFrm* pLayFrm,
641 : SwFrm* pLastLowerFrm = 0L )
642 : {
643 346 : SwFrm* pLowerFrm = pLayFrm->GetLower();
644 1004 : while ( pLowerFrm )
645 : {
646 : // #i44049#
647 512 : if ( pLastLowerFrm && pLowerFrm == pLastLowerFrm )
648 : {
649 200 : break;
650 : }
651 312 : if ( pLowerFrm->IsLayoutFrm() )
652 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pLowerFrm),
653 104 : pLastLowerFrm );
654 : else
655 208 : pLowerFrm->Calc();
656 :
657 312 : pLowerFrm = pLowerFrm->GetNext();
658 : }
659 346 : }
660 :
661 : /** method to format given anchor text frame and its previous frames
662 :
663 : #i56300#
664 : Usage: Needed to check, if the anchor text frame is moved forward
665 : due to the positioning and wrapping of its anchored objects, and
666 : to format the frames, which have become invalid due to the anchored
667 : object formatting in the iterative object positioning algorithm
668 : */
669 14952 : void SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm )
670 : {
671 : // #i47014# - no format of section and previous columns
672 : // for follow text frames.
673 14952 : if ( !_rAnchorTxtFrm.IsFollow() )
674 : {
675 : // if anchor frame is directly inside a section, format this section and
676 : // its previous frames.
677 : // Note: It's a very simple format without formatting objects.
678 14932 : if ( _rAnchorTxtFrm.IsInSct() )
679 : {
680 200 : SwFrm* pSectFrm = _rAnchorTxtFrm.GetUpper();
681 452 : while ( pSectFrm )
682 : {
683 252 : if ( pSectFrm->IsSctFrm() || pSectFrm->IsCellFrm() )
684 : {
685 200 : break;
686 : }
687 52 : pSectFrm = pSectFrm->GetUpper();
688 : }
689 200 : if ( pSectFrm && pSectFrm->IsSctFrm() )
690 : {
691 : // #i44049#
692 200 : _rAnchorTxtFrm.LockJoin();
693 200 : SwFrm* pFrm = pSectFrm->GetUpper()->GetLower();
694 : // #i49605# - section frame could move forward
695 : // by the format of its previous frame.
696 : // Thus, check for valid <pFrm>.
697 436 : while ( pFrm && pFrm != pSectFrm )
698 : {
699 36 : if ( pFrm->IsLayoutFrm() )
700 32 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
701 : else
702 4 : pFrm->Calc();
703 :
704 36 : pFrm = pFrm->GetNext();
705 : }
706 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pSectFrm),
707 200 : &_rAnchorTxtFrm );
708 : // #i44049#
709 200 : _rAnchorTxtFrm.UnlockJoin();
710 : }
711 : }
712 :
713 : // #i40140# - if anchor frame is inside a column,
714 : // format the content of the previous columns.
715 : // Note: It's a very simple format without formatting objects.
716 14932 : SwFrm* pColFrmOfAnchor = _rAnchorTxtFrm.FindColFrm();
717 14932 : if ( pColFrmOfAnchor )
718 : {
719 : // #i44049#
720 26 : _rAnchorTxtFrm.LockJoin();
721 26 : SwFrm* pColFrm = pColFrmOfAnchor->GetUpper()->GetLower();
722 62 : while ( pColFrm != pColFrmOfAnchor )
723 : {
724 10 : SwFrm* pFrm = pColFrm->GetLower();
725 30 : while ( pFrm )
726 : {
727 10 : if ( pFrm->IsLayoutFrm() )
728 10 : lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
729 : else
730 0 : pFrm->Calc();
731 :
732 10 : pFrm = pFrm->GetNext();
733 : }
734 :
735 10 : pColFrm = pColFrm->GetNext();
736 : }
737 : // #i44049#
738 26 : _rAnchorTxtFrm.UnlockJoin();
739 : }
740 : }
741 :
742 : // format anchor frame - format of its follow not needed
743 : // #i43255# - forbid follow format, only if anchor text
744 : // frame is in table
745 14952 : if ( _rAnchorTxtFrm.IsInTab() )
746 : {
747 1106 : SwForbidFollowFormat aForbidFollowFormat( _rAnchorTxtFrm );
748 1106 : _rAnchorTxtFrm.Calc();
749 : }
750 : else
751 : {
752 13846 : _rAnchorTxtFrm.Calc();
753 : }
754 14952 : }
755 :
756 : /** method to format the anchor frame for checking of the move forward condition
757 :
758 : #i40141#
759 : */
760 11440 : void SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()
761 : {
762 11440 : SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( mrAnchorTxtFrm );
763 11440 : }
764 :
765 : /** method to determine if at least one anchored object has state
766 : <temporarly consider wrapping style influence> set.
767 : */
768 1716 : bool SwObjectFormatterTxtFrm::_AtLeastOneObjIsTmpConsiderWrapInfluence()
769 : {
770 1716 : bool bRet( false );
771 :
772 1716 : const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
773 1716 : if ( pObjs && pObjs->size() > 1 )
774 : {
775 1462 : for ( size_t i = 0; i < pObjs->size(); ++i )
776 : {
777 1020 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
778 1020 : if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
779 : {
780 0 : bRet = true;
781 0 : break;
782 : }
783 : }
784 : }
785 :
786 1716 : return bRet;
787 270 : }
788 :
789 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|