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 .
20 #include <tocntntanchoredobjectposition.hxx>
21 #include <anchoredobject.hxx>
24 #include <pagefrm.hxx>
25 #include <sectfrm.hxx>
27 #include <rootfrm.hxx>
28 #include <viewopt.hxx>
31 #include <fmtsrnd.hxx>
32 #include <fmtfsize.hxx>
33 #include <fmtanchr.hxx>
34 #include <fmtornt.hxx>
35 #include <editeng/lrspitem.hxx>
36 #include <editeng/ulspitem.hxx>
37 #include <svx/svdobj.hxx>
38 #include <osl/diagnose.h>
39 #include <environmentofanchoredobject.hxx>
41 #include <fmtwrapinfluenceonobjpos.hxx>
42 #include <sortedobjs.hxx>
43 #include <textboxhelper.hxx>
44 #include <flyfrms.hxx>
46 using namespace ::com::sun::star
;
48 namespace objectpositioning
50 SwToContentAnchoredObjectPosition::SwToContentAnchoredObjectPosition( SdrObject
& _rDrawObj
)
51 : SwAnchoredObjectPosition ( _rDrawObj
),
52 mpVertPosOrientFrame( nullptr ),
53 mbAnchorToChar ( false ),
54 mpToCharOrientFrame( nullptr ),
55 mpToCharRect( nullptr ),
57 mnToCharTopOfLine( 0 )
60 SwToContentAnchoredObjectPosition::~SwToContentAnchoredObjectPosition()
63 bool SwToContentAnchoredObjectPosition::IsAnchoredToChar() const
65 return mbAnchorToChar
;
68 const SwFrame
* SwToContentAnchoredObjectPosition::ToCharOrientFrame() const
70 return mpToCharOrientFrame
;
73 const SwRect
* SwToContentAnchoredObjectPosition::ToCharRect() const
79 SwTwips
SwToContentAnchoredObjectPosition::ToCharTopOfLine() const
81 return mnToCharTopOfLine
;
84 SwTextFrame
& SwToContentAnchoredObjectPosition::GetAnchorTextFrame() const
86 assert( dynamic_cast<const SwTextFrame
*>( &GetAnchorFrame()) &&
87 "SwToContentAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
89 return static_cast<SwTextFrame
&>(GetAnchorFrame());
93 static bool lcl_DoesVertPosFits( const SwTwips _nRelPosY
,
94 const SwTwips _nAvail
,
95 const SwLayoutFrame
* _pUpperOfOrientFrame
,
97 const bool _bGrowInTable
,
98 SwLayoutFrame
*& _orpLayoutFrameToGrow
)
100 bool bVertPosFits
= false;
102 if ( _nRelPosY
<= _nAvail
)
108 if ( _pUpperOfOrientFrame
->IsInSct() )
110 SwSectionFrame
* pSctFrame
=
111 const_cast<SwSectionFrame
*>(_pUpperOfOrientFrame
->FindSctFrame());
112 bVertPosFits
= pSctFrame
->GetUpper()->Grow( _nRelPosY
- _nAvail
, true ) > 0;
113 // Note: do not provide a layout frame for a grow.
117 bVertPosFits
= const_cast<SwLayoutFrame
*>(_pUpperOfOrientFrame
)->
118 Grow( _nRelPosY
- _nAvail
, true ) > 0;
120 _orpLayoutFrameToGrow
= const_cast<SwLayoutFrame
*>(_pUpperOfOrientFrame
);
123 else if ( _pUpperOfOrientFrame
->IsInTab() && _bGrowInTable
)
125 // #i45085# - check, if upper frame would grow the
126 // expected amount of twips.
127 const SwTwips nTwipsGrown
= const_cast<SwLayoutFrame
*>(_pUpperOfOrientFrame
)->
128 Grow( _nRelPosY
- _nAvail
, true );
129 bVertPosFits
= ( nTwipsGrown
== ( _nRelPosY
- _nAvail
) );
131 _orpLayoutFrameToGrow
= const_cast<SwLayoutFrame
*>(_pUpperOfOrientFrame
);
137 void SwToContentAnchoredObjectPosition::CalcPosition()
139 // get format of object
140 const SwFrameFormat
& rFrameFormat
= GetFrameFormat();
142 // declare and set <pFooter> to footer frame, if object is anchored
143 // at a frame belonging to the footer.
144 const SwFrame
* pFooter
= GetAnchorFrame().FindFooterOrHeader();
145 if ( pFooter
&& !pFooter
->IsFooterFrame() )
148 // declare and set <bBrowse> to true, if document is in browser mode and
149 // object is anchored at the body, but not at frame belonging to a table.
150 bool bBrowse
= GetAnchorFrame().IsInDocBody() && !GetAnchorFrame().IsInTab();
153 const SwViewShell
*pSh
= GetAnchorFrame().getRootFrame()->GetCurrShell();
154 if( !pSh
|| !pSh
->GetViewOptions()->getBrowseMode() )
158 // determine left/right and its upper/lower spacing.
159 const SvxLRSpaceItem
&rLR
= rFrameFormat
.GetLRSpace();
160 const SvxULSpaceItem
&rUL
= rFrameFormat
.GetULSpace();
162 // determine, if object has no surrounding.
163 const SwFormatSurround
& rSurround
= rFrameFormat
.GetSurround();
164 const bool bNoSurround
= rSurround
.GetSurround() == css::text::WrapTextMode_NONE
;
165 const bool bWrapThrough
= rSurround
.GetSurround() == css::text::WrapTextMode_THROUGH
;
167 // new class <SwEnvironmentOfAnchoredObject>
168 SwEnvironmentOfAnchoredObject
aEnvOfObj( DoesObjFollowsTextFlow() );
170 // #i18732# - grow only, if object has to follow the text flow
171 const bool bGrow
= DoesObjFollowsTextFlow() &&
172 ( !GetAnchorFrame().IsInTab() ||
173 !rFrameFormat
.GetFrameSize().GetHeightPercent() );
175 // get text frame the object is anchored at
176 const SwTextFrame
& rAnchorTextFrame
= GetAnchorTextFrame();
177 SwRectFnSet
aRectFnSet(&rAnchorTextFrame
);
179 const SwRect
aObjBoundRect( GetAnchoredObj().GetObjRect() );
181 // local variable keeping the calculated relative position; initialized with
182 // current relative position.
183 // #i26791# - use new object instance of <SwAnchoredObject>
184 Point
aRelPos( GetAnchoredObj().GetCurrRelPos() );
186 SwTwips nRelDiff
= 0;
188 bool bMoveable
= rAnchorTextFrame
.IsMoveable();
190 // determine frame the object position has to be oriented at.
191 const SwTextFrame
* pOrientFrame
= &rAnchorTextFrame
;
192 const SwTextFrame
* pAnchorFrameForVertPos
;
193 // If true, this means that the anchored object is a split fly frame and it's not a master but
194 // one of the follows.
195 bool bFollowSplitFly
= false;
196 // The anchored object is a fly that is allowed to split.
197 bool bSplitFly
= false;
199 // if object is at-character anchored, determine character-rectangle
200 // and frame, position has to be oriented at.
201 mbAnchorToChar
= (RndStdIds::FLY_AT_CHAR
== rFrameFormat
.GetAnchor().GetAnchorId());
202 if ( mbAnchorToChar
)
204 const SwFormatAnchor
& rAnch
= rFrameFormat
.GetAnchor();
205 // #i26791# - use new object instance of <SwAnchoredObject>
206 // Due to table break algorithm the character
207 // rectangle can have no height. Thus, check also the width
208 if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
209 !GetAnchoredObj().GetLastCharRect().Width() ) ||
210 !GetAnchoredObj().GetLastTopOfLine() )
212 GetAnchoredObj().CheckCharRectAndTopOfLine( false );
213 // Due to table break algorithm the character
214 // rectangle can have no height. Thus, check also the width
215 if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
216 !GetAnchoredObj().GetLastCharRect().Width() ) ||
217 !GetAnchoredObj().GetLastTopOfLine() )
219 // Get default for <mpVertPosOrientFrame>, if it's not set.
220 if ( !mpVertPosOrientFrame
)
222 mpVertPosOrientFrame
= rAnchorTextFrame
.GetUpper();
227 mpToCharRect
= &(GetAnchoredObj().GetLastCharRect());
228 // #i22341# - get top of line, in which the anchor character is.
229 mnToCharTopOfLine
= GetAnchoredObj().GetLastTopOfLine();
230 pOrientFrame
= &(const_cast<SwTextFrame
&>(rAnchorTextFrame
).GetFrameAtOfst(
231 rAnchorTextFrame
.MapModelToViewPos(*rAnch
.GetContentAnchor())));
232 mpToCharOrientFrame
= pOrientFrame
;
234 else if (SwFlyFrame
* pFlyFrame
= GetAnchoredObj().DynCastFlyFrame())
236 // See if this fly is split. If so, then the anchor is also split. All anchors are
237 // empty, except the last follow.
238 if (pFlyFrame
->IsFlySplitAllowed())
240 auto pFlyAtContentFrame
= static_cast<SwFlyAtContentFrame
*>(pFlyFrame
);
241 // Decrement pFly to point to the master; increment pAnchor to point to the correct
243 SwFlyAtContentFrame
* pFly
= pFlyAtContentFrame
;
244 SwTextFrame
* pAnchor
= const_cast<SwTextFrame
*>(&rAnchorTextFrame
);
245 while (pFly
->GetPrecede())
247 pFly
= pFly
->GetPrecede();
250 SAL_WARN("sw.core", "SwToContentAnchoredObjectPosition::CalcPosition: fly "
251 "chain length is longer then anchor chain length");
254 pAnchor
= pAnchor
->GetFollow();
256 if (pAnchor
&& pAnchor
->GetPrecede())
258 pOrientFrame
= pAnchor
;
259 // Anchored object has a precede, so it's a follow.
260 bFollowSplitFly
= true;
266 aRectFnSet
.Refresh(pOrientFrame
);
268 // determine vertical position
271 // determine vertical positioning and alignment attributes
272 SwFormatVertOrient
aVert( rFrameFormat
.GetVertOrient() );
274 // #i18732# - determine layout frame for vertical
275 // positions aligned to 'page areas'.
276 const SwLayoutFrame
& rPageAlignLayFrame
=
277 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pOrientFrame
);
279 if ( aVert
.GetVertOrient() != text::VertOrientation::NONE
)
281 // #i18732# - adjustments for follow text flow or not
282 // AND vertical alignment at 'page areas'.
283 SwTwips nAlignAreaHeight
;
284 SwTwips nAlignAreaOffset
;
285 GetVertAlignmentValues( *pOrientFrame
, rPageAlignLayFrame
,
286 aVert
.GetRelationOrient(),
287 nAlignAreaHeight
, nAlignAreaOffset
);
290 const SwPageFrame
* aPageFrame
= pOrientFrame
->FindPageFrame();
291 const SwHeaderFrame
* pHeaderFrame
= aPageFrame
->GetHeaderFrame();
293 aHeaderRect
= pHeaderFrame
->GetPaintArea();
294 const SwTwips nTopMarginHeight
= aPageFrame
->GetTopMargin() + aHeaderRect
.Height();
295 const SwTwips nHeightBetweenOffsetAndMargin
= nAlignAreaOffset
+ nTopMarginHeight
;
297 // determine relative vertical position
298 SwTwips nRelPosY
= nAlignAreaOffset
;
299 const SwTwips nObjHeight
= aRectFnSet
.GetHeight(aObjBoundRect
);
300 const SwTwips nUpperSpace
= aRectFnSet
.IsVert()
301 ? ( aRectFnSet
.IsVertL2R()
305 // --> OD 2009-08-31 #monglianlayout#
306 const SwTwips nLowerSpace
= aRectFnSet
.IsVert()
307 ? ( aRectFnSet
.IsVertL2R()
311 switch ( aVert
.GetVertOrient() )
313 case text::VertOrientation::CHAR_BOTTOM
:
315 if ( mbAnchorToChar
)
317 // bottom (to character anchored)
318 nRelPosY
+= nAlignAreaHeight
+ nUpperSpace
;
319 if ( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
321 nRelPosY
+= nObjHeight
;
327 case text::VertOrientation::TOP
:
329 // #i22341# - special case for vertical
330 // alignment at top of line
331 if ( mbAnchorToChar
&&
332 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
334 nRelPosY
-= (nObjHeight
+ nLowerSpace
);
338 nRelPosY
+= nUpperSpace
;
343 case text::VertOrientation::LINE_TOP
:
345 if ( mbAnchorToChar
&&
346 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
348 nRelPosY
-= (nObjHeight
+ nLowerSpace
);
352 OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
356 case text::VertOrientation::CENTER
:
358 if (aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_TOP
)
359 nRelPosY
= (nAlignAreaOffset
/ 2) - (nObjHeight
/ 2) + (nHeightBetweenOffsetAndMargin
/ 2);
361 nRelPosY
+= (nAlignAreaHeight
/ 2) - (nObjHeight
/ 2);
365 case text::VertOrientation::LINE_CENTER
:
367 if ( mbAnchorToChar
&&
368 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
370 nRelPosY
+= (nAlignAreaHeight
/ 2) - (nObjHeight
/ 2);
374 OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
378 case text::VertOrientation::BOTTOM
:
380 if ( ( aVert
.GetRelationOrient() == text::RelOrientation::FRAME
||
381 aVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
) &&
384 // bottom (aligned to 'paragraph areas')
385 nRelPosY
+= nAlignAreaHeight
+ nUpperSpace
;
389 // #i22341# - special case for vertical
390 // alignment at top of line
391 if ( mbAnchorToChar
&&
392 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
394 nRelPosY
+= nUpperSpace
;
398 if (aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_TOP
)
399 nRelPosY
= 0 - (nObjHeight
+ nLowerSpace
) + nHeightBetweenOffsetAndMargin
;
401 nRelPosY
+= nAlignAreaHeight
- (nObjHeight
+ nLowerSpace
);
407 case text::VertOrientation::LINE_BOTTOM
:
409 if ( mbAnchorToChar
&&
410 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
)
412 nRelPosY
+= nUpperSpace
;
416 OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
424 // adjust relative position by distance between anchor frame and
425 // the frame, the object is oriented at.
426 // #i28701# - correction: adjust relative position,
427 // only if the floating screen object has to follow the text flow.
428 // Also don't do this for split flys: pOrientFrame already points to the follow anchor,
429 // so pOrientFrame is not the anchor text frame anymore, and that would lead to an
430 // additional, unwanted increase of nRelPosY.
431 if (DoesObjFollowsTextFlow() && pOrientFrame
!= &rAnchorTextFrame
&& !bFollowSplitFly
)
433 // #i11860# - use new method <GetTopForObjPos>
434 // to get top of frame for object positioning.
435 const SwTwips nTopOfOrient
= GetTopForObjPos( *pOrientFrame
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
436 nRelPosY
+= aRectFnSet
.YDiff( nTopOfOrient
,
437 GetTopForObjPos( rAnchorTextFrame
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() ) );
440 // #i42124# - capture object inside vertical
441 // layout environment.
443 const SwTwips nTopOfAnch
=
444 GetTopForObjPos( *pOrientFrame
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
445 const SwLayoutFrame
& rVertEnvironLayFrame
=
446 aEnvOfObj
.GetVertEnvironmentLayoutFrame(
447 *(pOrientFrame
->GetUpper()) );
448 const bool bCheckBottom
= !DoesObjFollowsTextFlow();
449 nRelPosY
= AdjustVertRelPos( nTopOfAnch
, aRectFnSet
.IsVert(), aRectFnSet
.IsVertL2R(),
450 rVertEnvironLayFrame
, nRelPosY
,
451 DoesObjFollowsTextFlow(),
455 // keep calculated relative vertical position - needed for filters
456 // (including the xml-filter)
458 // determine position
459 SwTwips nAttrRelPosY
= nRelPosY
- nAlignAreaOffset
;
461 if ( nAttrRelPosY
!= aVert
.GetPos() )
463 aVert
.SetPos( nAttrRelPosY
);
464 const_cast<SwFrameFormat
&>(rFrameFormat
).LockModify();
465 const_cast<SwFrameFormat
&>(rFrameFormat
).SetFormatAttr( aVert
);
466 const_cast<SwFrameFormat
&>(rFrameFormat
).UnlockModify();
470 // determine absolute 'vertical' position, depending on layout-direction
471 // #i26791# - determine offset to 'vertical' frame
472 // anchor position, depending on layout-direction
473 if ( aRectFnSet
.IsVert() )
475 aRelPos
.setX( nRelPosY
);
476 maOffsetToFrameAnchorPos
.setX( nAlignAreaOffset
);
480 aRelPos
.setY( nRelPosY
);
481 maOffsetToFrameAnchorPos
.setY( nAlignAreaOffset
);
485 // Determine upper of frame vertical position is oriented at.
486 // #i28701# - determine 'virtual' anchor frame.
487 // This frame is used in the following instead of the 'real' anchor
488 // frame <rAnchorTextFrame> for the 'vertical' position in all cases.
489 const SwLayoutFrame
* pUpperOfOrientFrame
= nullptr;
491 // #i28701# - As long as the anchor frame is on the
492 // same page as <pOrientFrame> and the vertical position isn't aligned
493 // automatic at the anchor character or the top of the line of the
494 // anchor character, the anchor frame determines the vertical position.
495 // Split fly follows: always let the anchor char frame determine the vertical position.
496 // This gives us a vertical cut position between the master and the follow.
497 if ( &rAnchorTextFrame
== pOrientFrame
||
498 ( rAnchorTextFrame
.FindPageFrame() == pOrientFrame
->FindPageFrame() &&
499 aVert
.GetVertOrient() == text::VertOrientation::NONE
&&
500 aVert
.GetRelationOrient() != text::RelOrientation::CHAR
&&
501 aVert
.GetRelationOrient() != text::RelOrientation::TEXT_LINE
&& !bFollowSplitFly
) )
503 pUpperOfOrientFrame
= rAnchorTextFrame
.GetUpper();
504 pAnchorFrameForVertPos
= &rAnchorTextFrame
;
508 pUpperOfOrientFrame
= pOrientFrame
->GetUpper();
509 pAnchorFrameForVertPos
= pOrientFrame
;
513 // ignore one-column sections.
514 // #i23512# - correction: also ignore one-columned
515 // sections with footnotes/endnotes
516 if ( pUpperOfOrientFrame
->IsInSct() )
518 const SwSectionFrame
* pSctFrame
= pUpperOfOrientFrame
->FindSctFrame();
519 const bool bIgnoreSection
= pUpperOfOrientFrame
->IsSctFrame() ||
520 ( pSctFrame
->Lower()->IsColumnFrame() &&
521 !pSctFrame
->Lower()->GetNext() );
522 if ( bIgnoreSection
)
523 pUpperOfOrientFrame
= pSctFrame
->GetUpper();
526 if ( aVert
.GetVertOrient() == text::VertOrientation::NONE
)
528 // local variable <nRelPosY> for calculation of relative vertical
529 // distance to anchor.
530 SwTwips nRelPosY
= 0;
531 // #i26791# - local variable <nVertOffsetToFrameAnchorPos>
532 // for determination of the 'vertical' offset to the frame anchor
534 SwTwips
nVertOffsetToFrameAnchorPos( 0 );
535 // #i22341# - add special case for vertical alignment
537 if ( mbAnchorToChar
&&
538 ( aVert
.GetRelationOrient() == text::RelOrientation::CHAR
||
539 aVert
.GetRelationOrient() == text::RelOrientation::TEXT_LINE
) )
541 // #i11860# - use new method <GetTopForObjPos>
542 // to get top of frame for object positioning.
543 SwTwips nTopOfOrient
= GetTopForObjPos( *pOrientFrame
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
544 if ( aVert
.GetRelationOrient() == text::RelOrientation::CHAR
)
546 nVertOffsetToFrameAnchorPos
= aRectFnSet
.YDiff(
547 aRectFnSet
.GetBottom(*ToCharRect()),
552 nVertOffsetToFrameAnchorPos
= aRectFnSet
.YDiff( ToCharTopOfLine(),
555 nRelPosY
= nVertOffsetToFrameAnchorPos
- aVert
.GetPos();
559 // #i28701# - correction: use <pAnchorFrameForVertPos>
560 // instead of <pOrientFrame> and do not adjust relative position
561 // to get correct vertical position.
562 nVertOffsetToFrameAnchorPos
= 0;
563 // #i11860# - use new method <GetTopForObjPos>
564 // to get top of frame for object positioning.
565 const SwTwips nTopOfOrient
=
566 GetTopForObjPos( *pAnchorFrameForVertPos
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
567 // Increase <nRelPosY> by margin height,
568 // if position is vertical aligned to "paragraph text area"
569 if ( aVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
)
571 // #i11860# - consider upper space amount of previous frame
572 SwTwips nTopMargin
= aRectFnSet
.GetTopMargin(*pAnchorFrameForVertPos
);
573 if ( pAnchorFrameForVertPos
->IsTextFrame() )
575 nTopMargin
-= pAnchorFrameForVertPos
->
576 GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid();
578 nVertOffsetToFrameAnchorPos
+= nTopMargin
;
580 // #i18732# - adjust <nRelPosY> by difference
581 // between 'page area' and 'anchor' frame, if position is
582 // vertical aligned to 'page areas'
583 else if (aVert
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
584 || aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_TOP
)
586 nVertOffsetToFrameAnchorPos
+= aRectFnSet
.YDiff(
587 aRectFnSet
.GetTop(rPageAlignLayFrame
.getFrameArea()),
590 else if ( aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
)
592 SwRect
aPgPrtRect( rPageAlignLayFrame
.getFrameArea() );
593 if ( rPageAlignLayFrame
.IsPageFrame() )
596 static_cast<const SwPageFrame
&>(rPageAlignLayFrame
).PrtWithoutHeaderAndFooter();
598 nVertOffsetToFrameAnchorPos
+= aRectFnSet
.YDiff(
599 aRectFnSet
.GetTop(aPgPrtRect
),
602 else if (aVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
)
604 // The anchored object is relative from the bottom of the page's print area.
605 SwRect
aPgPrtRect(rPageAlignLayFrame
.getFrameArea());
606 if (rPageAlignLayFrame
.IsPageFrame())
608 auto& rPageFrame
= static_cast<const SwPageFrame
&>(rPageAlignLayFrame
);
609 aPgPrtRect
= rPageFrame
.PrtWithoutHeaderAndFooter();
611 SwTwips nPageBottom
= aRectFnSet
.GetBottom(aPgPrtRect
);
612 nVertOffsetToFrameAnchorPos
+= aRectFnSet
.YDiff(nPageBottom
, nTopOfOrient
);
614 nRelPosY
= nVertOffsetToFrameAnchorPos
+ aVert
.GetPos();
617 // This is a follow of a split fly: shift it up to match the anchor position,
618 // because the vertical offset is meant to be handled only on the first page.
619 nRelPosY
-= aVert
.GetPos();
621 if (aVert
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
622 && rPageAlignLayFrame
.IsPageFrame())
624 // Master is positioned relative to the edge of the page, with an offset.
625 // Follow will have no offset, but is relative to the bottom of the header.
626 auto& rPageFrame
= static_cast<const SwPageFrame
&>(rPageAlignLayFrame
);
627 const SwLayoutFrame
* pBodyFrame
= rPageFrame
.FindBodyCont();
630 SwTwips nDiff
= pBodyFrame
->getFrameArea().Top()
631 - rPageFrame
.getFrameArea().Top();
638 // <pUpperOfOrientFrame>: layout frame, at which the position has to
640 // <nRelPosY>: rest of the relative distance in the current
642 // <nAvail>: space, which is available in the current
645 // #i26791# - determine offset to 'vertical'
646 // frame anchor position, depending on layout-direction
647 if ( aRectFnSet
.IsVert() )
648 maOffsetToFrameAnchorPos
.setX( nVertOffsetToFrameAnchorPos
);
650 maOffsetToFrameAnchorPos
.setY( nVertOffsetToFrameAnchorPos
);
651 // #i11860# - use new method <GetTopForObjPos>
652 // to get top of frame for object positioning.
653 const SwTwips nTopOfAnch
= GetTopForObjPos( *pAnchorFrameForVertPos
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
656 // Allow negative position, but keep it
657 // inside environment layout frame.
658 const SwLayoutFrame
& rVertEnvironLayFrame
=
659 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame
);
660 // #i31805# - do not check, if bottom of
661 // anchored object would fit into environment layout frame, if
662 // anchored object has to follow the text flow.
663 const bool bCheckBottom
= !DoesObjFollowsTextFlow();
664 nRelPosY
= AdjustVertRelPos( nTopOfAnch
, aRectFnSet
.IsVert(), aRectFnSet
.IsVertL2R(),
665 rVertEnvironLayFrame
, nRelPosY
,
666 DoesObjFollowsTextFlow(),
668 if ( aRectFnSet
.IsVert() )
669 aRelPos
.setX( nRelPosY
);
671 aRelPos
.setY( nRelPosY
);
675 aRectFnSet
.Refresh(pAnchorFrameForVertPos
);
677 aRectFnSet
.YDiff( aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
),
679 const bool bInFootnote
= pAnchorFrameForVertPos
->IsInFootnote();
682 // #i23512# - correction:
683 // consider section frame for grow in online layout.
684 // use new local method <lcl_DoesVertPosFits(..)>
685 SwLayoutFrame
* pLayoutFrameToGrow
= nullptr;
686 const bool bDoesVertPosFits
= lcl_DoesVertPosFits(
687 nRelPosY
, nAvail
, pUpperOfOrientFrame
, bBrowse
,
688 bGrow
, pLayoutFrameToGrow
);
690 if ( bDoesVertPosFits
)
692 SwTwips nTmpRelPosY
=
693 aRectFnSet
.YDiff( aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
),
696 // #i28701# - adjust calculated
697 // relative vertical position to object's environment.
698 const SwFrame
& rVertEnvironLayFrame
=
699 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame
);
700 // Do not check, if bottom of
701 // anchored object would fit into environment layout
702 // frame, if anchored object has to follow the text flow.
703 const bool bCheckBottom
= !DoesObjFollowsTextFlow();
704 nTmpRelPosY
= AdjustVertRelPos( nTopOfAnch
, aRectFnSet
.IsVert(), aRectFnSet
.IsVertL2R(),
705 rVertEnvironLayFrame
,
707 DoesObjFollowsTextFlow(),
709 if ( aRectFnSet
.IsVert() )
710 aRelPos
.setX( nTmpRelPosY
);
712 aRelPos
.setY( nTmpRelPosY
);
714 // #i23512# - use local variable
715 // <pLayoutFrameToGrow> provided by new method
716 // <lcl_DoesVertPosFits(..)>.
717 if ( pLayoutFrameToGrow
)
719 // No need to grow the anchor cell in case the follow-text-flow object
721 if (!GetAnchorFrame().IsInTab() || !DoesObjFollowsTextFlow() || !bWrapThrough
)
723 pLayoutFrameToGrow
->Grow( nRelPosY
- nAvail
);
730 // #i26495# - floating screen objects,
731 // which are anchored inside a table, doesn't follow
733 if ( DoesObjFollowsTextFlow() &&
734 ( aVert
.GetRelationOrient() != text::RelOrientation::PAGE_FRAME
&&
735 aVert
.GetRelationOrient() != text::RelOrientation::PAGE_PRINT_AREA
) &&
736 !GetAnchorFrame().IsInTab() )
740 // follow the text flow
742 MakePageType eMakePage
= bInFootnote
? MAKEPAGE_NONE
744 const bool bInSct
= pUpperOfOrientFrame
->IsInSct();
746 eMakePage
= MAKEPAGE_NOSECTION
;
748 const SwLayoutFrame
* pTmp
=
749 pUpperOfOrientFrame
->GetLeaf( eMakePage
, true, &rAnchorTextFrame
);
752 pUpperOfOrientFrame
->FindSctFrame()->IsAnFollow( pTmp
->FindSctFrame() ) ) )
754 pUpperOfOrientFrame
= pTmp
;
755 bMoveable
= rAnchorTextFrame
.IsMoveable( pUpperOfOrientFrame
);
756 aRectFnSet
.Refresh(pUpperOfOrientFrame
);
757 nAvail
= aRectFnSet
.GetHeight(pUpperOfOrientFrame
->getFramePrintArea());
761 // if there isn't enough space in the (columned)
762 // section, leave it and set available space <nAvail>
763 // to the space below the section.
764 // if the new available space isn't also enough,
765 // new pages can be created.
768 const SwFrame
* pSct
= pUpperOfOrientFrame
->FindSctFrame();
769 pUpperOfOrientFrame
= pSct
->GetUpper();
770 nAvail
= aRectFnSet
.YDiff(
771 aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
),
772 aRectFnSet
.GetPrtBottom(*pSct
) );
776 #if OSL_DEBUG_LEVEL > 1
777 OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - !bInSct" );
791 // #i18732# - do not follow text flow respectively
792 // align at 'page areas', but stay inside given environment
793 const SwFrame
& rVertEnvironLayFrame
=
794 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame
);
795 nRelPosY
= AdjustVertRelPos( nTopOfAnch
, aRectFnSet
.IsVert(), aRectFnSet
.IsVertL2R(),
796 rVertEnvironLayFrame
,
798 DoesObjFollowsTextFlow() );
799 if( aRectFnSet
.IsVert() )
800 aRelPos
.setX( nRelPosY
);
802 aRelPos
.setY( nRelPosY
);
806 } // end of <while ( nRelPosY )>
807 } // end of else <nRelPosY <= 0>
808 } // end of <aVert.GetVertOrient() == text::VertOrientation::NONE>
810 // We need to calculate the part's absolute position, in order for
811 // it to be put onto the right page and to be pulled into the
813 const SwTwips nTopOfAnch
= GetTopForObjPos( *pAnchorFrameForVertPos
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
814 if( aRectFnSet
.IsVert() )
816 // --> OD 2009-08-31 #monglianlayout#
817 if ( !aRectFnSet
.IsVertL2R() )
819 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
820 ( aRelPos
.X() - nRelDiff
) -
821 aObjBoundRect
.Width() );
825 GetAnchoredObj().SetObjLeft( nTopOfAnch
+
826 ( aRelPos
.X() - nRelDiff
) );
831 GetAnchoredObj().SetObjTop( nTopOfAnch
+
832 ( aRelPos
.Y() - nRelDiff
) );
835 // grow environment under certain conditions
836 // ignore one-column sections.
837 // #i23512# - correction: also ignore one-columned
838 // sections with footnotes/endnotes
839 if ( pUpperOfOrientFrame
->IsInSct() )
841 const SwSectionFrame
* pSctFrame
= pUpperOfOrientFrame
->FindSctFrame();
842 const bool bIgnoreSection
= pUpperOfOrientFrame
->IsSctFrame() ||
843 ( pSctFrame
->Lower()->IsColumnFrame() &&
844 !pSctFrame
->Lower()->GetNext() );
845 if ( bIgnoreSection
)
846 pUpperOfOrientFrame
= pSctFrame
->GetUpper();
848 SwTwips nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
849 aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
) );
852 // #i23512# - correction:
853 // consider section frame for grow in online layout and
854 // consider page alignment for grow in table.
855 SwLayoutFrame
* pLayoutFrameToGrow
= nullptr;
856 if ( bBrowse
&& rAnchorTextFrame
.IsMoveable() )
858 if ( pUpperOfOrientFrame
->IsInSct() )
860 pLayoutFrameToGrow
= const_cast<SwLayoutFrame
*>(
861 pUpperOfOrientFrame
->FindSctFrame()->GetUpper());
862 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
863 aRectFnSet
.GetPrtBottom(*pLayoutFrameToGrow
) );
866 pLayoutFrameToGrow
= nullptr;
872 const_cast<SwLayoutFrame
*>(pUpperOfOrientFrame
);
875 else if ( rAnchorTextFrame
.IsInTab() && bGrow
)
877 pLayoutFrameToGrow
= const_cast<SwLayoutFrame
*>(pUpperOfOrientFrame
);
879 if ( pLayoutFrameToGrow
)
881 // No need to grow the anchor cell in case the follow-text-flow object
883 if (!GetAnchorFrame().IsInTab() || !DoesObjFollowsTextFlow() || !bWrapThrough
)
885 pLayoutFrameToGrow
->Grow( -nDist
);
890 if ( DoesObjFollowsTextFlow() &&
891 ( aVert
.GetRelationOrient() != text::RelOrientation::PAGE_FRAME
&&
892 aVert
.GetRelationOrient() != text::RelOrientation::PAGE_PRINT_AREA
) )
895 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
896 aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
) );
897 // #i26945# - floating screen objects, which are
898 // anchored inside a table, doesn't follow the text flow. But, they
899 // have to stay inside its layout environment.
900 if ( nDist
< 0 && pOrientFrame
->IsInTab() )
902 // If the anchor frame is the first content of the table cell
903 // and has no follow, the table frame is notified,
904 // that the object doesn't fit into the table cell.
905 // Adjustment of position isn't needed in this case.
906 if ( pOrientFrame
== &rAnchorTextFrame
&&
907 !pOrientFrame
->GetFollow() &&
908 !pOrientFrame
->GetIndPrev() )
910 const_cast<SwTabFrame
*>(pOrientFrame
->FindTabFrame())
911 ->SetDoesObjsFit( false );
915 SwTwips
nTmpRelPosY( 0 );
916 if ( aRectFnSet
.IsVert() )
917 nTmpRelPosY
= aRelPos
.X() - nDist
;
919 nTmpRelPosY
= aRelPos
.Y() + nDist
;
920 const SwLayoutFrame
& rVertEnvironLayFrame
=
921 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame
);
922 nTmpRelPosY
= AdjustVertRelPos( nTopOfAnch
, aRectFnSet
.IsVert(), aRectFnSet
.IsVertL2R(),
923 rVertEnvironLayFrame
,
925 DoesObjFollowsTextFlow(),
927 if ( aRectFnSet
.IsVert() )
929 aRelPos
.setX( nTmpRelPosY
);
930 // --> OD 2009-08-31 #mongolianlayout#
931 if ( !aRectFnSet
.IsVertL2R() )
933 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
935 aObjBoundRect
.Width() );
939 GetAnchoredObj().SetObjLeft( nTopOfAnch
+ aRelPos
.X() );
944 aRelPos
.setY( nTmpRelPosY
);
945 GetAnchoredObj().SetObjTop( nTopOfAnch
+ aRelPos
.Y() );
947 // If the anchor frame is the first content of the table cell
948 // and the object still doesn't fit, the table frame is notified,
949 // that the object doesn't fit into the table cell.
950 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
951 aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
) );
953 pOrientFrame
== &rAnchorTextFrame
&& !pOrientFrame
->GetIndPrev() )
955 const_cast<SwTabFrame
*>(pOrientFrame
->FindTabFrame())
956 ->SetDoesObjsFit( false );
960 // Don't move split flys around for follow text flow purposes; if they don't fit their
961 // parent anymore, they will shrink and part of the content will move to the follow fly.
965 const bool bInFootnote
= rAnchorTextFrame
.IsInFootnote();
966 while( bMoveable
&& nDist
< 0 )
968 bool bInSct
= pUpperOfOrientFrame
->IsInSct();
971 const SwLayoutFrame
* pTmp
= pUpperOfOrientFrame
->FindSctFrame()->GetUpper();
972 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
973 aRectFnSet
.GetPrtBottom(*pTmp
) );
974 // #i23129# - Try to flow into next
975 // section|section column. Thus, do *not* leave section
976 // area, if anchored object doesn't fit into upper of section.
977 // But the anchored object is allowed to overlap bottom
978 // section|section column.
985 aRectFnSet
.GetTop(GetAnchoredObj().GetObjRect()) ==
986 aRectFnSet
.GetPrtTop(*pUpperOfOrientFrame
) )
987 // It doesn't fit, moving it would not help either anymore
990 const SwLayoutFrame
* pNextLay
= pUpperOfOrientFrame
->GetLeaf(
993 : ( bInFootnote
? MAKEPAGE_NONE
: MAKEPAGE_APPEND
) ),
994 true, &rAnchorTextFrame
);
996 // If anchor is in footnote and proposed next layout environment
997 // isn't a footnote frame, object can't follow the text flow
998 if ( bInFootnote
&& pNextLay
&& !pNextLay
->IsFootnoteFrame() )
1004 SwRectFnSet
fnRectX(pNextLay
);
1006 ( pUpperOfOrientFrame
->FindSctFrame()->IsAnFollow( pNextLay
->FindSctFrame() ) &&
1007 fnRectX
.GetHeight(pNextLay
->getFramePrintArea()) ) )
1009 SwTwips nTmpRelPosY
=
1010 aRectFnSet
.YDiff( aRectFnSet
.GetPrtTop(*pNextLay
),
1012 if ( aRectFnSet
.IsVert() )
1013 aRelPos
.setX( nTmpRelPosY
);
1015 aRelPos
.setY( nTmpRelPosY
);
1016 pUpperOfOrientFrame
= pNextLay
;
1017 aRectFnSet
.Refresh(pUpperOfOrientFrame
);
1018 bMoveable
= rAnchorTextFrame
.IsMoveable( pUpperOfOrientFrame
);
1019 if( fnRectX
.IsVert() )
1021 // --> OD 2009-08-31 #mongolianlayout#
1022 if ( !aRectFnSet
.IsVertL2R() )
1024 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
1026 aObjBoundRect
.Width() );
1030 GetAnchoredObj().SetObjLeft( nTopOfAnch
+
1035 GetAnchoredObj().SetObjTop( nTopOfAnch
+
1037 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
1038 aRectFnSet
.GetPrtBottom(*pUpperOfOrientFrame
) );
1040 // #i23129# - leave section area
1043 const SwLayoutFrame
* pTmp
= pUpperOfOrientFrame
->FindSctFrame()->GetUpper();
1044 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
1045 aRectFnSet
.GetPrtBottom(*pTmp
) );
1047 pUpperOfOrientFrame
= pTmp
;
1054 // If we don't have enough room within the Area, we take a look at
1056 const SwLayoutFrame
* pTmp
= pUpperOfOrientFrame
->FindSctFrame()->GetUpper();
1057 nDist
= aRectFnSet
.BottomDist( GetAnchoredObj().GetObjRect(),
1058 aRectFnSet
.GetPrtBottom(*pTmp
) );
1060 pUpperOfOrientFrame
= pTmp
;
1070 // keep layout frame vertical position is oriented at.
1071 mpVertPosOrientFrame
= pUpperOfOrientFrame
;
1073 // If it was requested to not overlap with already formatted objects, take care of that
1075 CalcOverlap(pAnchorFrameForVertPos
, aRelPos
, nTopOfAnch
);
1078 // determine 'horizontal' position
1080 // determine horizontal positioning and alignment attributes
1081 SwFormatHoriOrient
aHori( rFrameFormat
.GetHoriOrient() );
1083 // set calculated vertical position in order to determine correct
1084 // frame, the horizontal position is oriented at.
1085 const SwTwips nTopOfAnch
= GetTopForObjPos( *pAnchorFrameForVertPos
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
1086 if( aRectFnSet
.IsVert() )
1088 // --> OD 2009-08-31 #mongolianlayout#
1089 if ( !aRectFnSet
.IsVertL2R() )
1091 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
1092 aRelPos
.X() - aObjBoundRect
.Width() );
1096 GetAnchoredObj().SetObjLeft( nTopOfAnch
+ aRelPos
.X() );
1100 GetAnchoredObj().SetObjTop( nTopOfAnch
+ aRelPos
.Y() );
1102 // determine frame, horizontal position is oriented at.
1103 // #i28701# - If floating screen object doesn't follow
1104 // the text flow, its horizontal position is oriented at <pOrientFrame>.
1105 const SwFrame
* pHoriOrientFrame
= DoesObjFollowsTextFlow()
1106 ? &GetHoriVirtualAnchor( *mpVertPosOrientFrame
)
1109 // #i26791# - get 'horizontal' offset to frame anchor position.
1110 SwTwips
nHoriOffsetToFrameAnchorPos( 0 );
1111 SwTwips nRelPosX
= CalcRelPosX( *pHoriOrientFrame
, aEnvOfObj
,
1112 aHori
, rLR
, rUL
, bWrapThrough
,
1113 ( aRectFnSet
.IsVert() ? aRelPos
.X() : aRelPos
.Y() ),
1114 nHoriOffsetToFrameAnchorPos
);
1116 // #i26791# - determine offset to 'horizontal' frame
1117 // anchor position, depending on layout-direction
1118 if ( aRectFnSet
.IsVert() )
1120 aRelPos
.setY( nRelPosX
);
1121 maOffsetToFrameAnchorPos
.setY( nHoriOffsetToFrameAnchorPos
);
1125 aRelPos
.setX( nRelPosX
);
1126 maOffsetToFrameAnchorPos
.setX( nHoriOffsetToFrameAnchorPos
);
1129 // save calculated horizontal position - needed for filters
1130 // (including the xml-filter)
1132 SwTwips nAttrRelPosX
= nRelPosX
- nHoriOffsetToFrameAnchorPos
;
1133 if ( aHori
.GetHoriOrient() != text::HoriOrientation::NONE
&&
1134 aHori
.GetPos() != nAttrRelPosX
)
1136 aHori
.SetPos( nAttrRelPosX
);
1137 const_cast<SwFrameFormat
&>(rFrameFormat
).LockModify();
1138 const_cast<SwFrameFormat
&>(rFrameFormat
).SetFormatAttr( aHori
);
1139 const_cast<SwFrameFormat
&>(rFrameFormat
).UnlockModify();
1144 // set absolute position at object
1145 const SwTwips nTopOfAnch
= GetTopForObjPos( *pAnchorFrameForVertPos
, aRectFnSet
.FnRect(), aRectFnSet
.IsVert() );
1146 if( aRectFnSet
.IsVert() )
1148 // --> OD 2009-08-31 #mongolianlayout#
1149 if ( !aRectFnSet
.IsVertL2R() )
1151 GetAnchoredObj().SetObjLeft( nTopOfAnch
-
1152 aRelPos
.X() - aObjBoundRect
.Width() );
1156 GetAnchoredObj().SetObjLeft( nTopOfAnch
+ aRelPos
.X() );
1158 GetAnchoredObj().SetObjTop( rAnchorTextFrame
.getFrameArea().Top() +
1163 GetAnchoredObj().SetObjLeft( rAnchorTextFrame
.getFrameArea().Left() +
1165 GetAnchoredObj().SetObjTop( nTopOfAnch
+ aRelPos
.Y() );
1168 // set relative position at object
1169 GetAnchoredObj().SetCurrRelPos( aRelPos
);
1172 void SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame
* pAnchorFrameForVertPos
,
1173 Point
& rRelPos
, const SwTwips nTopOfAnch
)
1175 const SwFrameFormat
& rFrameFormat
= GetFrameFormat();
1176 bool bAllowOverlap
= rFrameFormat
.GetWrapInfluenceOnObjPos().GetAllowOverlap();
1182 if (rFrameFormat
.GetSurround().GetSurround() == css::text::WrapTextMode_THROUGH
)
1184 // This is explicit wrap through: allowed to overlap.
1188 if (SwTextBoxHelper::isTextBox(&rFrameFormat
, RES_FLYFRMFMT
))
1190 // This is the frame part of a textbox, just take the offset from the textbox's shape part.
1191 SwFrameFormat
* pShapeOfTextBox
1192 = SwTextBoxHelper::getOtherTextBoxFormat(&rFrameFormat
, RES_FLYFRMFMT
);
1193 if (pShapeOfTextBox
)
1195 SwTwips nYDiff
= pShapeOfTextBox
->GetWrapInfluenceOnObjPos().GetOverlapVertOffset();
1198 rRelPos
.setY(rRelPos
.getY() + nYDiff
+ 1);
1199 GetAnchoredObj().SetObjTop(nTopOfAnch
+ rRelPos
.Y());
1205 // Get the list of objects.
1206 auto pSortedObjs
= pAnchorFrameForVertPos
->GetDrawObjs();
1207 const SwLayoutFrame
* pAnchorUpper
= pAnchorFrameForVertPos
->GetUpper();
1209 bool bSplitFly
= false;
1210 SwFlyFrame
* pFlyFrame
= GetAnchoredObj().DynCastFlyFrame();
1211 if (pFlyFrame
&& pFlyFrame
->IsFlySplitAllowed())
1213 // At least for split flys we need to consider objects on the same page, but anchored in
1214 // different text frames.
1217 SwFrame
* pFlyFrameAnchor
= pFlyFrame
->GetAnchorFrameContainingAnchPos();
1218 if (pFlyFrameAnchor
&& pFlyFrameAnchor
->IsInFly())
1220 // An inner fly overlapping with its outer fly is fine.
1224 const SwPageFrame
* pPageFrame
= pAnchorFrameForVertPos
->FindPageFrame();
1227 pSortedObjs
= pPageFrame
->GetSortedObjs();
1236 for (const auto& pAnchoredObj
: *pSortedObjs
)
1238 if (pAnchoredObj
== &GetAnchoredObj())
1240 // We found ourselves, stop iterating.
1244 if (SwTextBoxHelper::isTextBox(&pAnchoredObj
->GetFrameFormat(), RES_FLYFRMFMT
))
1246 // Overlapping with the frame of a textbox is fine.
1250 SwFlyFrame
* pAnchoredObjFly
= pAnchoredObj
->DynCastFlyFrame();
1253 if (!pAnchoredObjFly
)
1255 // This is a split fly, then overlap is only checked against other split flys.
1259 if (pAnchoredObjFly
->getRootFrame()->IsInFlyDelList(pAnchoredObjFly
))
1261 // A fly overlapping with a to-be-deleted fly is fine.
1265 SwFrame
* pAnchoredObjFlyAnchor
= pAnchoredObjFly
->GetAnchorFrameContainingAnchPos();
1266 if (pAnchoredObjFlyAnchor
&& pAnchoredObjFlyAnchor
->IsInFly())
1268 // An inner fly overlapping with its outer fly is fine.
1272 if (pAnchoredObjFlyAnchor
&& pAnchoredObjFlyAnchor
->GetUpper() != pAnchorUpper
)
1274 // A fly overlapping with a fly from an other upper is fine.
1279 css::text::WrapTextMode eWrap
= pAnchoredObj
->GetFrameFormat().GetSurround().GetSurround();
1280 if (eWrap
== css::text::WrapTextMode_THROUGH
)
1282 // The other object is wrap through: allowed to overlap.
1286 if (!GetAnchoredObj().GetObjRect().Overlaps(pAnchoredObj
->GetObjRect()))
1288 // Found an already positioned object, but it doesn't overlap, ignore.
1292 // Already formatted, overlaps: resolve the conflict by shifting ourselves down.
1293 SwTwips nYDiff
= pAnchoredObj
->GetObjRect().Bottom() - GetAnchoredObj().GetObjRect().Top();
1294 rRelPos
.setY(rRelPos
.getY() + nYDiff
+ 1);
1295 GetAnchoredObj().SetObjTop(nTopOfAnch
+ rRelPos
.Y());
1297 // Store our offset that avoids the overlap. If this is a shape of a textbox, then the frame
1298 // of the textbox will use it.
1299 SwFormatWrapInfluenceOnObjPos
aInfluence(rFrameFormat
.GetWrapInfluenceOnObjPos());
1300 aInfluence
.SetOverlapVertOffset(nYDiff
);
1301 const_cast<SwFrameFormat
&>(rFrameFormat
).LockModify();
1302 const_cast<SwFrameFormat
&>(rFrameFormat
).SetFormatAttr(aInfluence
);
1303 const_cast<SwFrameFormat
&>(rFrameFormat
).UnlockModify();
1308 * Determine frame for horizontal position
1310 const SwFrame
& SwToContentAnchoredObjectPosition::GetHoriVirtualAnchor(
1311 const SwLayoutFrame
& _rProposedFrame
) const
1313 const SwFrame
* pHoriVirtAnchFrame
= &_rProposedFrame
;
1315 // Search for first lower content frame, which is the anchor or a follow
1316 // of the anchor (Note: <Anchor.IsAnFollow( Anchor )> is true)
1317 // If none found, <_rProposedFrame> is returned.
1318 const SwFrame
* pFrame
= _rProposedFrame
.Lower();
1321 if ( pFrame
->IsContentFrame() &&
1322 GetAnchorTextFrame().IsAnFollow( static_cast<const SwContentFrame
*>(pFrame
) ) )
1324 pHoriVirtAnchFrame
= pFrame
;
1327 pFrame
= pFrame
->GetNext();
1330 return *pHoriVirtAnchFrame
;
1335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */