LibreOffice Module sw (master)  1
tocntntanchoredobjectposition.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 
21 #include <anchoredobject.hxx>
22 #include <frame.hxx>
23 #include <txtfrm.hxx>
24 #include <pagefrm.hxx>
25 #include <sectfrm.hxx>
26 #include <tabfrm.hxx>
27 #include <rootfrm.hxx>
28 #include <viewopt.hxx>
29 #include <viewsh.hxx>
30 #include <frmfmt.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>
40 #include <frmatr.hxx>
42 #include <sortedobjs.hxx>
43 #include <textboxhelper.hxx>
44 
45 using namespace objectpositioning;
46 using namespace ::com::sun::star;
47 
49  : SwAnchoredObjectPosition ( _rDrawObj ),
50  mpVertPosOrientFrame( nullptr ),
51  mbAnchorToChar ( false ),
52  mpToCharOrientFrame( nullptr ),
53  mpToCharRect( nullptr ),
54  // #i22341#
55  mnToCharTopOfLine( 0 )
56 {}
57 
59 {}
60 
62 {
63  return mbAnchorToChar;
64 }
65 
67 {
68  return mpToCharOrientFrame;
69 }
70 
72 {
73  return mpToCharRect;
74 }
75 
76 // #i22341#
78 {
79  return mnToCharTopOfLine;
80 }
81 
83 {
84  assert( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame()) &&
85  "SwToContentAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
86 
87  return static_cast<SwTextFrame&>(GetAnchorFrame());
88 }
89 
90 // #i23512#
91 static bool lcl_DoesVertPosFits( const SwTwips _nRelPosY,
92  const SwTwips _nAvail,
93  const SwLayoutFrame* _pUpperOfOrientFrame,
94  const bool _bBrowse,
95  const bool _bGrowInTable,
96  SwLayoutFrame*& _orpLayoutFrameToGrow )
97 {
98  bool bVertPosFits = false;
99 
100  if ( _nRelPosY <= _nAvail )
101  {
102  bVertPosFits = true;
103  }
104  else if ( _bBrowse )
105  {
106  if ( _pUpperOfOrientFrame->IsInSct() )
107  {
108  SwSectionFrame* pSctFrame =
109  const_cast<SwSectionFrame*>(_pUpperOfOrientFrame->FindSctFrame());
110  bVertPosFits = pSctFrame->GetUpper()->Grow( _nRelPosY - _nAvail, true ) > 0;
111  // Note: do not provide a layout frame for a grow.
112  }
113  else
114  {
115  bVertPosFits = const_cast<SwLayoutFrame*>(_pUpperOfOrientFrame)->
116  Grow( _nRelPosY - _nAvail, true ) > 0;
117  if ( bVertPosFits )
118  _orpLayoutFrameToGrow = const_cast<SwLayoutFrame*>(_pUpperOfOrientFrame);
119  }
120  }
121  else if ( _pUpperOfOrientFrame->IsInTab() && _bGrowInTable )
122  {
123  // #i45085# - check, if upper frame would grow the
124  // expected amount of twips.
125  const SwTwips nTwipsGrown = const_cast<SwLayoutFrame*>(_pUpperOfOrientFrame)->
126  Grow( _nRelPosY - _nAvail, true );
127  bVertPosFits = ( nTwipsGrown == ( _nRelPosY - _nAvail ) );
128  if ( bVertPosFits )
129  _orpLayoutFrameToGrow = const_cast<SwLayoutFrame*>(_pUpperOfOrientFrame);
130  }
131 
132  return bVertPosFits;
133 }
134 
136 {
137  // get format of object
138  const SwFrameFormat& rFrameFormat = GetFrameFormat();
139 
140  // declare and set <pFooter> to footer frame, if object is anchored
141  // at a frame belonging to the footer.
142  const SwFrame* pFooter = GetAnchorFrame().FindFooterOrHeader();
143  if ( pFooter && !pFooter->IsFooterFrame() )
144  pFooter = nullptr;
145 
146  // declare and set <bBrowse> to true, if document is in browser mode and
147  // object is anchored at the body, but not at frame belonging to a table.
148  bool bBrowse = GetAnchorFrame().IsInDocBody() && !GetAnchorFrame().IsInTab();
149  if( bBrowse )
150  {
152  if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
153  bBrowse = false;
154  }
155 
156  // determine left/right and its upper/lower spacing.
157  const SvxLRSpaceItem &rLR = rFrameFormat.GetLRSpace();
158  const SvxULSpaceItem &rUL = rFrameFormat.GetULSpace();
159 
160  // determine, if object has no surrounding.
161  const SwFormatSurround& rSurround = rFrameFormat.GetSurround();
162  const bool bNoSurround = rSurround.GetSurround() == css::text::WrapTextMode_NONE;
163  const bool bWrapThrough = rSurround.GetSurround() == css::text::WrapTextMode_THROUGH;
164 
165  // new class <SwEnvironmentOfAnchoredObject>
167 
168  // #i18732# - grow only, if object has to follow the text flow
169  const bool bGrow = DoesObjFollowsTextFlow() &&
170  ( !GetAnchorFrame().IsInTab() ||
171  !rFrameFormat.GetFrameSize().GetHeightPercent() );
172 
173  // get text frame the object is anchored at
174  const SwTextFrame& rAnchorTextFrame = GetAnchorTextFrame();
175  SwRectFnSet aRectFnSet(&rAnchorTextFrame);
176 
177  const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
178 
179  // local variable keeping the calculated relative position; initialized with
180  // current relative position.
181  // #i26791# - use new object instance of <SwAnchoredObject>
182  Point aRelPos( GetAnchoredObj().GetCurrRelPos() );
183 
184  SwTwips nRelDiff = 0;
185 
186  bool bMoveable = rAnchorTextFrame.IsMoveable();
187 
188  // determine frame the object position has to be oriented at.
189  const SwTextFrame* pOrientFrame = &rAnchorTextFrame;
190  const SwTextFrame* pAnchorFrameForVertPos;
191  {
192  // if object is at-character anchored, determine character-rectangle
193  // and frame, position has to be oriented at.
194  mbAnchorToChar = (RndStdIds::FLY_AT_CHAR == rFrameFormat.GetAnchor().GetAnchorId());
195  if ( mbAnchorToChar )
196  {
197  const SwFormatAnchor& rAnch = rFrameFormat.GetAnchor();
198  // #i26791# - use new object instance of <SwAnchoredObject>
199  // Due to table break algorithm the character
200  // rectangle can have no height. Thus, check also the width
201  if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
202  !GetAnchoredObj().GetLastCharRect().Width() ) ||
203  !GetAnchoredObj().GetLastTopOfLine() )
204  {
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() )
211  {
212  // Get default for <mpVertPosOrientFrame>, if it's not set.
213  if ( !mpVertPosOrientFrame )
214  {
215  mpVertPosOrientFrame = rAnchorTextFrame.GetUpper();
216  }
217  return;
218  }
219  }
221  // #i22341# - get top of line, in which the anchor character is.
223  pOrientFrame = &(const_cast<SwTextFrame&>(rAnchorTextFrame).GetFrameAtOfst(
224  rAnchorTextFrame.MapModelToViewPos(*rAnch.GetContentAnchor())));
225  mpToCharOrientFrame = pOrientFrame;
226  }
227  }
228  aRectFnSet.Refresh(pOrientFrame);
229 
230  // determine vertical position
231  {
232 
233  // determine vertical positioning and alignment attributes
234  SwFormatVertOrient aVert( rFrameFormat.GetVertOrient() );
235 
236  // #i18732# - determine layout frame for vertical
237  // positions aligned to 'page areas'.
238  const SwLayoutFrame& rPageAlignLayFrame =
239  aEnvOfObj.GetVertEnvironmentLayoutFrame( *pOrientFrame );
240 
241  if ( aVert.GetVertOrient() != text::VertOrientation::NONE )
242  {
243  // #i18732# - adjustments for follow text flow or not
244  // AND vertical alignment at 'page areas'.
245  SwTwips nAlignAreaHeight;
246  SwTwips nAlignAreaOffset;
247  GetVertAlignmentValues( *pOrientFrame, rPageAlignLayFrame,
248  aVert.GetRelationOrient(),
249  nAlignAreaHeight, nAlignAreaOffset );
250 
251  SwRect aHeaderRect;
252  const SwPageFrame* aPageFrame = pOrientFrame->FindPageFrame();
253  const SwHeaderFrame* pHeaderFrame = aPageFrame->GetHeaderFrame();
254  if (pHeaderFrame)
255  aHeaderRect = pHeaderFrame->GetPaintArea();
256  const SwTwips nTopMarginHeight = aPageFrame->GetTopMargin() + aHeaderRect.Height();
257  const SwTwips nHeightBetweenOffsetAndMargin = nAlignAreaOffset + nTopMarginHeight;
258 
259  // determine relative vertical position
260  SwTwips nRelPosY = nAlignAreaOffset;
261  const SwTwips nObjHeight = aRectFnSet.GetHeight(aObjBoundRect);
262  const SwTwips nUpperSpace = aRectFnSet.IsVert()
263  ? ( aRectFnSet.IsVertL2R()
264  ? rLR.GetLeft()
265  : rLR.GetRight() )
266  : rUL.GetUpper();
267  // --> OD 2009-08-31 #monglianlayout#
268  const SwTwips nLowerSpace = aRectFnSet.IsVert()
269  ? ( aRectFnSet.IsVertL2R()
270  ? rLR.GetLeft()
271  : rLR.GetRight() )
272  : rUL.GetLower();
273  switch ( aVert.GetVertOrient() )
274  {
275  case text::VertOrientation::CHAR_BOTTOM:
276  {
277  if ( mbAnchorToChar )
278  {
279  // bottom (to character anchored)
280  nRelPosY += nAlignAreaHeight + nUpperSpace;
281  if ( aRectFnSet.IsVert() && !aRectFnSet.IsVertL2R() )
282  {
283  nRelPosY += nObjHeight;
284  }
285  break;
286  }
287  [[fallthrough]];
288  }
289  case text::VertOrientation::TOP:
290  {
291  // #i22341# - special case for vertical
292  // alignment at top of line
293  if ( mbAnchorToChar &&
294  aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
295  {
296  nRelPosY -= (nObjHeight + nLowerSpace);
297  }
298  else
299  {
300  nRelPosY += nUpperSpace;
301  }
302  }
303  break;
304  // #i22341#
305  case text::VertOrientation::LINE_TOP:
306  {
307  if ( mbAnchorToChar &&
308  aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
309  {
310  nRelPosY -= (nObjHeight + nLowerSpace);
311  }
312  else
313  {
314  OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
315  }
316  }
317  break;
318  case text::VertOrientation::CENTER:
319  {
320  if (aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_TOP)
321  nRelPosY = (nAlignAreaOffset / 2) - (nObjHeight / 2) + (nHeightBetweenOffsetAndMargin / 2);
322  else
323  nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
324  }
325  break;
326  // #i22341#
327  case text::VertOrientation::LINE_CENTER:
328  {
329  if ( mbAnchorToChar &&
330  aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
331  {
332  nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
333  }
334  else
335  {
336  OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
337  }
338  }
339  break;
340  case text::VertOrientation::BOTTOM:
341  {
342  if ( ( aVert.GetRelationOrient() == text::RelOrientation::FRAME ||
343  aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
344  bNoSurround )
345  {
346  // bottom (aligned to 'paragraph areas')
347  nRelPosY += nAlignAreaHeight + nUpperSpace;
348  }
349  else
350  {
351  // #i22341# - special case for vertical
352  // alignment at top of line
353  if ( mbAnchorToChar &&
354  aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
355  {
356  nRelPosY += nUpperSpace;
357  }
358  else
359  {
360  if (aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_TOP)
361  nRelPosY = 0 - (nObjHeight + nLowerSpace) + nHeightBetweenOffsetAndMargin;
362  else
363  nRelPosY += nAlignAreaHeight - (nObjHeight + nLowerSpace);
364  }
365  }
366  }
367  break;
368  // #i22341#
369  case text::VertOrientation::LINE_BOTTOM:
370  {
371  if ( mbAnchorToChar &&
372  aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
373  {
374  nRelPosY += nUpperSpace;
375  }
376  else
377  {
378  OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
379  }
380  }
381  break;
382  default:
383  break;
384  }
385 
386  // adjust relative position by distance between anchor frame and
387  // the frame, the object is oriented at.
388  // #i28701# - correction: adjust relative position,
389  // only if the floating screen object has to follow the text flow.
390  if ( DoesObjFollowsTextFlow() && pOrientFrame != &rAnchorTextFrame )
391  {
392  // #i11860# - use new method <GetTopForObjPos>
393  // to get top of frame for object positioning.
394  const SwTwips nTopOfOrient = GetTopForObjPos( *pOrientFrame, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
395  nRelPosY += aRectFnSet.YDiff( nTopOfOrient,
396  GetTopForObjPos( rAnchorTextFrame, aRectFnSet.FnRect(), aRectFnSet.IsVert() ) );
397  }
398 
399  // #i42124# - capture object inside vertical
400  // layout environment.
401  {
402  const SwTwips nTopOfAnch =
403  GetTopForObjPos( *pOrientFrame, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
404  const SwLayoutFrame& rVertEnvironLayFrame =
406  *(pOrientFrame->GetUpper()) );
407  const bool bCheckBottom = !DoesObjFollowsTextFlow();
408  nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
409  rVertEnvironLayFrame, nRelPosY,
411  bCheckBottom );
412  }
413 
414  // keep calculated relative vertical position - needed for filters
415  // (including the xml-filter)
416  {
417  // determine position
418  SwTwips nAttrRelPosY = nRelPosY - nAlignAreaOffset;
419  // set
420  if ( nAttrRelPosY != aVert.GetPos() )
421  {
422  aVert.SetPos( nAttrRelPosY );
423  const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
424  const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr( aVert );
425  const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
426  }
427  }
428 
429  // determine absolute 'vertical' position, depending on layout-direction
430  // #i26791# - determine offset to 'vertical' frame
431  // anchor position, depending on layout-direction
432  if ( aRectFnSet.IsVert() )
433  {
434  aRelPos.setX( nRelPosY );
435  maOffsetToFrameAnchorPos.setX( nAlignAreaOffset );
436  }
437  else
438  {
439  aRelPos.setY( nRelPosY );
440  maOffsetToFrameAnchorPos.setY( nAlignAreaOffset );
441  }
442  }
443 
444  // Determine upper of frame vertical position is oriented at.
445  // #i28701# - determine 'virtual' anchor frame.
446  // This frame is used in the following instead of the 'real' anchor
447  // frame <rAnchorTextFrame> for the 'vertical' position in all cases.
448  const SwLayoutFrame* pUpperOfOrientFrame = nullptr;
449  {
450  // #i28701# - As long as the anchor frame is on the
451  // same page as <pOrientFrame> and the vertical position isn't aligned
452  // automatic at the anchor character or the top of the line of the
453  // anchor character, the anchor frame determines the vertical position.
454  if ( &rAnchorTextFrame == pOrientFrame ||
455  ( rAnchorTextFrame.FindPageFrame() == pOrientFrame->FindPageFrame() &&
456  aVert.GetVertOrient() == text::VertOrientation::NONE &&
457  aVert.GetRelationOrient() != text::RelOrientation::CHAR &&
458  aVert.GetRelationOrient() != text::RelOrientation::TEXT_LINE ) )
459  {
460  pUpperOfOrientFrame = rAnchorTextFrame.GetUpper();
461  pAnchorFrameForVertPos = &rAnchorTextFrame;
462  }
463  else
464  {
465  pUpperOfOrientFrame = pOrientFrame->GetUpper();
466  pAnchorFrameForVertPos = pOrientFrame;
467  }
468  }
469 
470  // ignore one-column sections.
471  // #i23512# - correction: also ignore one-columned
472  // sections with footnotes/endnotes
473  if ( pUpperOfOrientFrame->IsInSct() )
474  {
475  const SwSectionFrame* pSctFrame = pUpperOfOrientFrame->FindSctFrame();
476  const bool bIgnoreSection = pUpperOfOrientFrame->IsSctFrame() ||
477  ( pSctFrame->Lower()->IsColumnFrame() &&
478  !pSctFrame->Lower()->GetNext() );
479  if ( bIgnoreSection )
480  pUpperOfOrientFrame = pSctFrame->GetUpper();
481  }
482 
483  if ( aVert.GetVertOrient() == text::VertOrientation::NONE )
484  {
485  // local variable <nRelPosY> for calculation of relative vertical
486  // distance to anchor.
487  SwTwips nRelPosY = 0;
488  // #i26791# - local variable <nVertOffsetToFrameAnchorPos>
489  // for determination of the 'vertical' offset to the frame anchor
490  // position
491  SwTwips nVertOffsetToFrameAnchorPos( 0 );
492  // #i22341# - add special case for vertical alignment
493  // at top of line.
494  if ( mbAnchorToChar &&
495  ( aVert.GetRelationOrient() == text::RelOrientation::CHAR ||
496  aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) )
497  {
498  // #i11860# - use new method <GetTopForObjPos>
499  // to get top of frame for object positioning.
500  SwTwips nTopOfOrient = GetTopForObjPos( *pOrientFrame, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
501  if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR )
502  {
503  nVertOffsetToFrameAnchorPos = aRectFnSet.YDiff(
504  aRectFnSet.GetBottom(*ToCharRect()),
505  nTopOfOrient );
506  }
507  else
508  {
509  nVertOffsetToFrameAnchorPos = aRectFnSet.YDiff( ToCharTopOfLine(),
510  nTopOfOrient );
511  }
512  nRelPosY = nVertOffsetToFrameAnchorPos - aVert.GetPos();
513  }
514  else
515  {
516  // #i28701# - correction: use <pAnchorFrameForVertPos>
517  // instead of <pOrientFrame> and do not adjust relative position
518  // to get correct vertical position.
519  nVertOffsetToFrameAnchorPos = 0;
520  // #i11860# - use new method <GetTopForObjPos>
521  // to get top of frame for object positioning.
522  const SwTwips nTopOfOrient =
523  GetTopForObjPos( *pAnchorFrameForVertPos, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
524  // Increase <nRelPosY> by margin height,
525  // if position is vertical aligned to "paragraph text area"
526  if ( aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
527  {
528  // #i11860# - consider upper space amount of previous frame
529  SwTwips nTopMargin = aRectFnSet.GetTopMargin(*pAnchorFrameForVertPos);
530  if ( pAnchorFrameForVertPos->IsTextFrame() )
531  {
532  nTopMargin -= pAnchorFrameForVertPos->
533  GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid();
534  }
535  nVertOffsetToFrameAnchorPos += nTopMargin;
536  }
537  // #i18732# - adjust <nRelPosY> by difference
538  // between 'page area' and 'anchor' frame, if position is
539  // vertical aligned to 'page areas'
540  else if (aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
541  || aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_TOP)
542  {
543  nVertOffsetToFrameAnchorPos += aRectFnSet.YDiff(
544  aRectFnSet.GetTop(rPageAlignLayFrame.getFrameArea()),
545  nTopOfOrient );
546  }
547  else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
548  {
549  SwRect aPgPrtRect( rPageAlignLayFrame.getFrameArea() );
550  if ( rPageAlignLayFrame.IsPageFrame() )
551  {
552  aPgPrtRect =
553  static_cast<const SwPageFrame&>(rPageAlignLayFrame).PrtWithoutHeaderAndFooter();
554  }
555  nVertOffsetToFrameAnchorPos += aRectFnSet.YDiff(
556  aRectFnSet.GetTop(aPgPrtRect),
557  nTopOfOrient );
558  }
559  else if (aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM)
560  {
561  // The anchored object is relative from the bottom of the page's print area.
562  SwRect aPgPrtRect(rPageAlignLayFrame.getFrameArea());
563  if (rPageAlignLayFrame.IsPageFrame())
564  {
565  auto& rPageFrame = static_cast<const SwPageFrame&>(rPageAlignLayFrame);
566  aPgPrtRect = rPageFrame.PrtWithoutHeaderAndFooter();
567  }
568  SwTwips nPageBottom = aRectFnSet.GetBottom(aPgPrtRect);
569  nVertOffsetToFrameAnchorPos += aRectFnSet.YDiff(nPageBottom, nTopOfOrient);
570  }
571  nRelPosY = nVertOffsetToFrameAnchorPos + aVert.GetPos();
572  }
573 
574  // <pUpperOfOrientFrame>: layout frame, at which the position has to
575  // is oriented at
576  // <nRelPosY>: rest of the relative distance in the current
577  // layout frame
578  // <nAvail>: space, which is available in the current
579  // layout frame
580 
581  // #i26791# - determine offset to 'vertical'
582  // frame anchor position, depending on layout-direction
583  if ( aRectFnSet.IsVert() )
584  maOffsetToFrameAnchorPos.setX( nVertOffsetToFrameAnchorPos );
585  else
586  maOffsetToFrameAnchorPos.setY( nVertOffsetToFrameAnchorPos );
587  // #i11860# - use new method <GetTopForObjPos>
588  // to get top of frame for object positioning.
589  const SwTwips nTopOfAnch = GetTopForObjPos( *pAnchorFrameForVertPos, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
590  if( nRelPosY <= 0 )
591  {
592  // Allow negative position, but keep it
593  // inside environment layout frame.
594  const SwLayoutFrame& rVertEnvironLayFrame =
595  aEnvOfObj.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame );
596  // #i31805# - do not check, if bottom of
597  // anchored object would fit into environment layout frame, if
598  // anchored object has to follow the text flow.
599  const bool bCheckBottom = !DoesObjFollowsTextFlow();
600  nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
601  rVertEnvironLayFrame, nRelPosY,
603  bCheckBottom );
604  if ( aRectFnSet.IsVert() )
605  aRelPos.setX( nRelPosY );
606  else
607  aRelPos.setY( nRelPosY );
608  }
609  else
610  {
611  aRectFnSet.Refresh(pAnchorFrameForVertPos);
612  SwTwips nAvail =
613  aRectFnSet.YDiff( aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame),
614  nTopOfAnch );
615  const bool bInFootnote = pAnchorFrameForVertPos->IsInFootnote();
616  while ( nRelPosY )
617  {
618  // #i23512# - correction:
619  // consider section frame for grow in online layout.
620  // use new local method <lcl_DoesVertPosFits(..)>
621  SwLayoutFrame* pLayoutFrameToGrow = nullptr;
622  const bool bDoesVertPosFits = lcl_DoesVertPosFits(
623  nRelPosY, nAvail, pUpperOfOrientFrame, bBrowse,
624  bGrow, pLayoutFrameToGrow );
625 
626  if ( bDoesVertPosFits )
627  {
628  SwTwips nTmpRelPosY =
629  aRectFnSet.YDiff( aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame),
630  nTopOfAnch ) -
631  nAvail + nRelPosY;
632  // #i28701# - adjust calculated
633  // relative vertical position to object's environment.
634  const SwFrame& rVertEnvironLayFrame =
635  aEnvOfObj.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame );
636  // Do not check, if bottom of
637  // anchored object would fit into environment layout
638  // frame, if anchored object has to follow the text flow.
639  const bool bCheckBottom = !DoesObjFollowsTextFlow();
640  nTmpRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
641  rVertEnvironLayFrame,
642  nTmpRelPosY,
644  bCheckBottom );
645  if ( aRectFnSet.IsVert() )
646  aRelPos.setX( nTmpRelPosY );
647  else
648  aRelPos.setY( nTmpRelPosY );
649 
650  // #i23512# - use local variable
651  // <pLayoutFrameToGrow> provided by new method
652  // <lcl_DoesVertPosFits(..)>.
653  if ( pLayoutFrameToGrow )
654  {
655  // No need to grow the anchor cell in case the follow-text-flow object
656  // is wrap-though.
657  if (!GetAnchorFrame().IsInTab() || !DoesObjFollowsTextFlow() || !bWrapThrough)
658  {
659  pLayoutFrameToGrow->Grow( nRelPosY - nAvail );
660  }
661  }
662  nRelPosY = 0;
663  }
664  else
665  {
666  // #i26495# - floating screen objects,
667  // which are anchored inside a table, doesn't follow
668  // the text flow.
669  if ( DoesObjFollowsTextFlow() &&
670  ( aVert.GetRelationOrient() != text::RelOrientation::PAGE_FRAME &&
671  aVert.GetRelationOrient() != text::RelOrientation::PAGE_PRINT_AREA ) &&
672  !GetAnchorFrame().IsInTab() )
673  {
674  if ( bMoveable )
675  {
676  // follow the text flow
677  nRelPosY -= nAvail;
678  MakePageType eMakePage = bInFootnote ? MAKEPAGE_NONE
679  : MAKEPAGE_APPEND;
680  const bool bInSct = pUpperOfOrientFrame->IsInSct();
681  if( bInSct )
682  eMakePage = MAKEPAGE_NOSECTION;
683 
684  const SwLayoutFrame* pTmp =
685  pUpperOfOrientFrame->GetLeaf( eMakePage, true, &rAnchorTextFrame );
686  if ( pTmp &&
687  ( !bInSct ||
688  pUpperOfOrientFrame->FindSctFrame()->IsAnFollow( pTmp->FindSctFrame() ) ) )
689  {
690  pUpperOfOrientFrame = pTmp;
691  bMoveable = rAnchorTextFrame.IsMoveable( pUpperOfOrientFrame );
692  aRectFnSet.Refresh(pUpperOfOrientFrame);
693  nAvail = aRectFnSet.GetHeight(pUpperOfOrientFrame->getFramePrintArea());
694  }
695  else
696  {
697  // if there isn't enough space in the (columned)
698  // section, leave it and set available space <nAvail>
699  // to the space below the section.
700  // if the new available space isn't also enough,
701  // new pages can be created.
702  if( bInSct )
703  {
704  const SwFrame* pSct = pUpperOfOrientFrame->FindSctFrame();
705  pUpperOfOrientFrame = pSct->GetUpper();
706  nAvail = aRectFnSet.YDiff(
707  aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame),
708  aRectFnSet.GetPrtBottom(*pSct) );
709  }
710  else
711  {
712 #if OSL_DEBUG_LEVEL > 1
713  OSL_FAIL( "<SwToContentAnchoredObjectPosition::CalcPosition()> - !bInSct" );
714 #endif
715  nRelDiff = nRelPosY;
716  nRelPosY = 0;
717  }
718  }
719  }
720  else
721  {
722  nRelPosY = 0;
723  }
724  }
725  else
726  {
727  // #i18732# - do not follow text flow respectively
728  // align at 'page areas', but stay inside given environment
729  const SwFrame& rVertEnvironLayFrame =
730  aEnvOfObj.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame );
731  nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
732  rVertEnvironLayFrame,
733  nRelPosY,
735  if( aRectFnSet.IsVert() )
736  aRelPos.setX( nRelPosY );
737  else
738  aRelPos.setY( nRelPosY );
739  nRelPosY = 0;
740  }
741  }
742  } // end of <while ( nRelPosY )>
743  } // end of else <nRelPosY <= 0>
744  } // end of <aVert.GetVertOrient() == text::VertOrientation::NONE>
745 
746  // We need to calculate the part's absolute position, in order for
747  // it to be put onto the right page and to be pulled into the
748  // LayLeaf's PrtArea
749  const SwTwips nTopOfAnch = GetTopForObjPos( *pAnchorFrameForVertPos, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
750  if( aRectFnSet.IsVert() )
751  {
752  // --> OD 2009-08-31 #monglianlayout#
753  if ( !aRectFnSet.IsVertL2R() )
754  {
755  GetAnchoredObj().SetObjLeft( nTopOfAnch -
756  ( aRelPos.X() - nRelDiff ) -
757  aObjBoundRect.Width() );
758  }
759  else
760  {
761  GetAnchoredObj().SetObjLeft( nTopOfAnch +
762  ( aRelPos.X() - nRelDiff ) );
763  }
764  }
765  else
766  {
767  GetAnchoredObj().SetObjTop( nTopOfAnch +
768  ( aRelPos.Y() - nRelDiff ) );
769  }
770 
771  // grow environment under certain conditions
772  // ignore one-column sections.
773  // #i23512# - correction: also ignore one-columned
774  // sections with footnotes/endnotes
775  if ( pUpperOfOrientFrame->IsInSct() )
776  {
777  const SwSectionFrame* pSctFrame = pUpperOfOrientFrame->FindSctFrame();
778  const bool bIgnoreSection = pUpperOfOrientFrame->IsSctFrame() ||
779  ( pSctFrame->Lower()->IsColumnFrame() &&
780  !pSctFrame->Lower()->GetNext() );
781  if ( bIgnoreSection )
782  pUpperOfOrientFrame = pSctFrame->GetUpper();
783  }
784  SwTwips nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
785  aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame) );
786  if( nDist < 0 )
787  {
788  // #i23512# - correction:
789  // consider section frame for grow in online layout and
790  // consider page alignment for grow in table.
791  SwLayoutFrame* pLayoutFrameToGrow = nullptr;
792  if ( bBrowse && rAnchorTextFrame.IsMoveable() )
793  {
794  if ( pUpperOfOrientFrame->IsInSct() )
795  {
796  pLayoutFrameToGrow = const_cast<SwLayoutFrame*>(
797  pUpperOfOrientFrame->FindSctFrame()->GetUpper());
798  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
799  aRectFnSet.GetPrtBottom(*pLayoutFrameToGrow) );
800  if ( nDist >= 0 )
801  {
802  pLayoutFrameToGrow = nullptr;
803  }
804  }
805  else
806  {
807  pLayoutFrameToGrow =
808  const_cast<SwLayoutFrame*>(pUpperOfOrientFrame);
809  }
810  }
811  else if ( rAnchorTextFrame.IsInTab() && bGrow )
812  {
813  pLayoutFrameToGrow = const_cast<SwLayoutFrame*>(pUpperOfOrientFrame);
814  }
815  if ( pLayoutFrameToGrow )
816  {
817  // No need to grow the anchor cell in case the follow-text-flow object
818  // is wrap-though.
819  if (!GetAnchorFrame().IsInTab() || !DoesObjFollowsTextFlow() || !bWrapThrough)
820  {
821  pLayoutFrameToGrow->Grow( -nDist );
822  }
823  }
824  }
825 
826  if ( DoesObjFollowsTextFlow() &&
827  ( aVert.GetRelationOrient() != text::RelOrientation::PAGE_FRAME &&
828  aVert.GetRelationOrient() != text::RelOrientation::PAGE_PRINT_AREA ) )
829  {
830 
831  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
832  aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame) );
833  // #i26945# - floating screen objects, which are
834  // anchored inside a table, doesn't follow the text flow. But, they
835  // have to stay inside its layout environment.
836  if ( nDist < 0 && pOrientFrame->IsInTab() )
837  {
838  // If the anchor frame is the first content of the table cell
839  // and has no follow, the table frame is notified,
840  // that the object doesn't fit into the table cell.
841  // Adjustment of position isn't needed in this case.
842  if ( pOrientFrame == &rAnchorTextFrame &&
843  !pOrientFrame->GetFollow() &&
844  !pOrientFrame->GetIndPrev() )
845  {
846  const_cast<SwTabFrame*>(pOrientFrame->FindTabFrame())
847  ->SetDoesObjsFit( false );
848  }
849  else
850  {
851  SwTwips nTmpRelPosY( 0 );
852  if ( aRectFnSet.IsVert() )
853  nTmpRelPosY = aRelPos.X() - nDist;
854  else
855  nTmpRelPosY = aRelPos.Y() + nDist;
856  const SwLayoutFrame& rVertEnvironLayFrame =
857  aEnvOfObj.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame );
858  nTmpRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
859  rVertEnvironLayFrame,
860  nTmpRelPosY,
862  false );
863  if ( aRectFnSet.IsVert() )
864  {
865  aRelPos.setX( nTmpRelPosY );
866  // --> OD 2009-08-31 #mongolianlayout#
867  if ( !aRectFnSet.IsVertL2R() )
868  {
869  GetAnchoredObj().SetObjLeft( nTopOfAnch -
870  aRelPos.X() -
871  aObjBoundRect.Width() );
872  }
873  else
874  {
875  GetAnchoredObj().SetObjLeft( nTopOfAnch + aRelPos.X() );
876  }
877  }
878  else
879  {
880  aRelPos.setY( nTmpRelPosY );
881  GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
882  }
883  // If the anchor frame is the first content of the table cell
884  // and the object still doesn't fit, the table frame is notified,
885  // that the object doesn't fit into the table cell.
886  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
887  aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame) );
888  if ( nDist < 0 &&
889  pOrientFrame == &rAnchorTextFrame && !pOrientFrame->GetIndPrev() )
890  {
891  const_cast<SwTabFrame*>(pOrientFrame->FindTabFrame())
892  ->SetDoesObjsFit( false );
893  }
894  }
895  }
896  else
897  {
898  // follow text flow
899  const bool bInFootnote = rAnchorTextFrame.IsInFootnote();
900  while( bMoveable && nDist < 0 )
901  {
902  bool bInSct = pUpperOfOrientFrame->IsInSct();
903  if ( bInSct )
904  {
905  const SwLayoutFrame* pTmp = pUpperOfOrientFrame->FindSctFrame()->GetUpper();
906  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
907  aRectFnSet.GetPrtBottom(*pTmp) );
908  // #i23129# - Try to flow into next
909  // section|section column. Thus, do *not* leave section
910  // area, if anchored object doesn't fit into upper of section.
911  // But the anchored object is allowed to overlap bottom
912  // section|section column.
913  if ( nDist >= 0 )
914  {
915  break;
916  }
917  }
918  if ( !bInSct &&
919  aRectFnSet.GetTop(GetAnchoredObj().GetObjRect()) ==
920  aRectFnSet.GetPrtTop(*pUpperOfOrientFrame) )
921  // It doesn't fit, moving it would not help either anymore
922  break;
923 
924  const SwLayoutFrame* pNextLay = pUpperOfOrientFrame->GetLeaf(
925  ( bInSct
927  : ( bInFootnote ? MAKEPAGE_NONE : MAKEPAGE_APPEND ) ),
928  true, &rAnchorTextFrame );
929  // correction:
930  // If anchor is in footnote and proposed next layout environment
931  // isn't a footnote frame, object can't follow the text flow
932  if ( bInFootnote && pNextLay && !pNextLay->IsFootnoteFrame() )
933  {
934  pNextLay = nullptr;
935  }
936  if ( pNextLay )
937  {
938  SwRectFnSet fnRectX(pNextLay);
939  if ( !bInSct ||
940  ( pUpperOfOrientFrame->FindSctFrame()->IsAnFollow( pNextLay->FindSctFrame() ) &&
941  fnRectX.GetHeight(pNextLay->getFramePrintArea()) ) )
942  {
943  SwTwips nTmpRelPosY =
944  aRectFnSet.YDiff( aRectFnSet.GetPrtTop(*pNextLay),
945  nTopOfAnch );
946  if ( aRectFnSet.IsVert() )
947  aRelPos.setX( nTmpRelPosY );
948  else
949  aRelPos.setY( nTmpRelPosY );
950  pUpperOfOrientFrame = pNextLay;
951  aRectFnSet.Refresh(pUpperOfOrientFrame);
952  bMoveable = rAnchorTextFrame.IsMoveable( pUpperOfOrientFrame );
953  if( fnRectX.IsVert() )
954  {
955  // --> OD 2009-08-31 #mongolianlayout#
956  if ( !aRectFnSet.IsVertL2R() )
957  {
958  GetAnchoredObj().SetObjLeft( nTopOfAnch -
959  aRelPos.X() -
960  aObjBoundRect.Width() );
961  }
962  else
963  {
964  GetAnchoredObj().SetObjLeft( nTopOfAnch +
965  aRelPos.X() );
966  }
967  }
968  else
969  GetAnchoredObj().SetObjTop( nTopOfAnch +
970  aRelPos.Y() );
971  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
972  aRectFnSet.GetPrtBottom(*pUpperOfOrientFrame) );
973  }
974  // #i23129# - leave section area
975  else if ( bInSct )
976  {
977  const SwLayoutFrame* pTmp = pUpperOfOrientFrame->FindSctFrame()->GetUpper();
978  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
979  aRectFnSet.GetPrtBottom(*pTmp) );
980  if( nDist < 0 )
981  pUpperOfOrientFrame = pTmp;
982  else
983  break;
984  }
985  }
986  else if ( bInSct )
987  {
988  // If we don't have enough room within the Area, we take a look at
989  // the Page
990  const SwLayoutFrame* pTmp = pUpperOfOrientFrame->FindSctFrame()->GetUpper();
991  nDist = aRectFnSet.BottomDist( GetAnchoredObj().GetObjRect(),
992  aRectFnSet.GetPrtBottom(*pTmp) );
993  if( nDist < 0 )
994  pUpperOfOrientFrame = pTmp;
995  else
996  break;
997  }
998  else
999  bMoveable = false;
1000  }
1001  }
1002  }
1003 
1004  // keep layout frame vertical position is oriented at.
1005  mpVertPosOrientFrame = pUpperOfOrientFrame;
1006 
1007  // If it was requested to not overlap with already formatted objects, take care of that
1008  // here.
1009  CalcOverlap(pAnchorFrameForVertPos, aRelPos, nTopOfAnch);
1010  }
1011 
1012  // determine 'horizontal' position
1013  {
1014  // determine horizontal positioning and alignment attributes
1015  SwFormatHoriOrient aHori( rFrameFormat.GetHoriOrient() );
1016 
1017  // set calculated vertical position in order to determine correct
1018  // frame, the horizontal position is oriented at.
1019  const SwTwips nTopOfAnch = GetTopForObjPos( *pAnchorFrameForVertPos, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
1020  if( aRectFnSet.IsVert() )
1021  {
1022  // --> OD 2009-08-31 #mongolianlayout#
1023  if ( !aRectFnSet.IsVertL2R() )
1024  {
1025  GetAnchoredObj().SetObjLeft( nTopOfAnch -
1026  aRelPos.X() - aObjBoundRect.Width() );
1027  }
1028  else
1029  {
1030  GetAnchoredObj().SetObjLeft( nTopOfAnch + aRelPos.X() );
1031  }
1032  }
1033  else
1034  GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
1035 
1036  // determine frame, horizontal position is oriented at.
1037  // #i28701# - If floating screen object doesn't follow
1038  // the text flow, its horizontal position is oriented at <pOrientFrame>.
1039  const SwFrame* pHoriOrientFrame = DoesObjFollowsTextFlow()
1041  : pOrientFrame;
1042 
1043  // #i26791# - get 'horizontal' offset to frame anchor position.
1044  SwTwips nHoriOffsetToFrameAnchorPos( 0 );
1045  SwTwips nRelPosX = CalcRelPosX( *pHoriOrientFrame, aEnvOfObj,
1046  aHori, rLR, rUL, bWrapThrough,
1047  ( aRectFnSet.IsVert() ? aRelPos.X() : aRelPos.Y() ),
1048  nHoriOffsetToFrameAnchorPos );
1049 
1050  // #i26791# - determine offset to 'horizontal' frame
1051  // anchor position, depending on layout-direction
1052  if ( aRectFnSet.IsVert() )
1053  {
1054  aRelPos.setY( nRelPosX );
1055  maOffsetToFrameAnchorPos.setY( nHoriOffsetToFrameAnchorPos );
1056  }
1057  else
1058  {
1059  aRelPos.setX( nRelPosX );
1060  maOffsetToFrameAnchorPos.setX( nHoriOffsetToFrameAnchorPos );
1061  }
1062 
1063  // save calculated horizontal position - needed for filters
1064  // (including the xml-filter)
1065  {
1066  SwTwips nAttrRelPosX = nRelPosX - nHoriOffsetToFrameAnchorPos;
1067  if ( aHori.GetHoriOrient() != text::HoriOrientation::NONE &&
1068  aHori.GetPos() != nAttrRelPosX )
1069  {
1070  aHori.SetPos( nAttrRelPosX );
1071  const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
1072  const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr( aHori );
1073  const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
1074  }
1075  }
1076  }
1077 
1078  // set absolute position at object
1079  const SwTwips nTopOfAnch = GetTopForObjPos( *pAnchorFrameForVertPos, aRectFnSet.FnRect(), aRectFnSet.IsVert() );
1080  if( aRectFnSet.IsVert() )
1081  {
1082  // --> OD 2009-08-31 #mongolianlayout#
1083  if ( !aRectFnSet.IsVertL2R() )
1084  {
1085  GetAnchoredObj().SetObjLeft( nTopOfAnch -
1086  aRelPos.X() - aObjBoundRect.Width() );
1087  }
1088  else
1089  {
1090  GetAnchoredObj().SetObjLeft( nTopOfAnch + aRelPos.X() );
1091  }
1092  GetAnchoredObj().SetObjTop( rAnchorTextFrame.getFrameArea().Top() +
1093  aRelPos.Y() );
1094  }
1095  else
1096  {
1097  GetAnchoredObj().SetObjLeft( rAnchorTextFrame.getFrameArea().Left() +
1098  aRelPos.X() );
1099  GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
1100  }
1101 
1102  // set relative position at object
1103  GetAnchoredObj().SetCurrRelPos( aRelPos );
1104 }
1105 
1107  Point& rRelPos, const SwTwips nTopOfAnch)
1108 {
1109  const SwFrameFormat& rFrameFormat = GetFrameFormat();
1110  bool bAllowOverlap = rFrameFormat.GetWrapInfluenceOnObjPos().GetAllowOverlap();
1111  if (bAllowOverlap)
1112  {
1113  return;
1114  }
1115 
1116  if (rFrameFormat.GetSurround().GetSurround() == css::text::WrapTextMode_THROUGH)
1117  {
1118  // This is explicit wrap through: allowed to overlap.
1119  return;
1120  }
1121 
1122  if (SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT))
1123  {
1124  // This is the frame part of a textbox, just take the offset from the textbox's shape part.
1125  SwFrameFormat* pShapeOfTextBox
1127  if (pShapeOfTextBox)
1128  {
1129  SwTwips nYDiff = pShapeOfTextBox->GetWrapInfluenceOnObjPos().GetOverlapVertOffset();
1130  if (nYDiff > 0)
1131  {
1132  rRelPos.setY(rRelPos.getY() + nYDiff + 1);
1133  GetAnchoredObj().SetObjTop(nTopOfAnch + rRelPos.Y());
1134  }
1135  }
1136  return;
1137  }
1138 
1139  // Get the list of objects.
1140  auto pSortedObjs = pAnchorFrameForVertPos->GetDrawObjs();
1141  if (!pSortedObjs)
1142  {
1143  return;
1144  }
1145 
1146  for (const auto& pAnchoredObj : *pSortedObjs)
1147  {
1148  if (pAnchoredObj == &GetAnchoredObj())
1149  {
1150  // We found ourselves, stop iterating.
1151  break;
1152  }
1153 
1154  if (SwTextBoxHelper::isTextBox(&pAnchoredObj->GetFrameFormat(), RES_FLYFRMFMT))
1155  {
1156  // Overlapping with the frame of a textbox is fine.
1157  continue;
1158  }
1159 
1160  css::text::WrapTextMode eWrap = pAnchoredObj->GetFrameFormat().GetSurround().GetSurround();
1161  if (eWrap == css::text::WrapTextMode_THROUGH)
1162  {
1163  // The other object is wrap through: allowed to overlap.
1164  continue;
1165  }
1166 
1167  if (!GetAnchoredObj().GetObjRect().Overlaps(pAnchoredObj->GetObjRect()))
1168  {
1169  // Found an already positioned object, but it doesn't overlap, ignore.
1170  continue;
1171  }
1172 
1173  // Already formatted, overlaps: resolve the conflict by shifting ourselves down.
1174  SwTwips nYDiff = pAnchoredObj->GetObjRect().Bottom() - GetAnchoredObj().GetObjRect().Top();
1175  rRelPos.setY(rRelPos.getY() + nYDiff + 1);
1176  GetAnchoredObj().SetObjTop(nTopOfAnch + rRelPos.Y());
1177 
1178  // Store our offset that avoids the overlap. If this is a shape of a textbox, then the frame
1179  // of the textbox will use it.
1180  SwFormatWrapInfluenceOnObjPos aInfluence(rFrameFormat.GetWrapInfluenceOnObjPos());
1181  aInfluence.SetOverlapVertOffset(nYDiff);
1182  const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
1183  const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr(aInfluence);
1184  const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
1185  }
1186 }
1187 
1192  const SwLayoutFrame& _rProposedFrame ) const
1193 {
1194  const SwFrame* pHoriVirtAnchFrame = &_rProposedFrame;
1195 
1196  // Search for first lower content frame, which is the anchor or a follow
1197  // of the anchor (Note: <Anchor.IsAnFollow( Anchor )> is true)
1198  // If none found, <_rProposedFrame> is returned.
1199  const SwFrame* pFrame = _rProposedFrame.Lower();
1200  while ( pFrame )
1201  {
1202  if ( pFrame->IsContentFrame() &&
1203  GetAnchorTextFrame().IsAnFollow( static_cast<const SwContentFrame*>(pFrame) ) )
1204  {
1205  pHoriVirtAnchFrame = pFrame;
1206  break;
1207  }
1208  pFrame = pFrame->GetNext();
1209  }
1210 
1211  return *pHoriVirtAnchFrame;
1212 }
1213 
1214 
1215 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwFrame * FindFooterOrHeader()
Definition: findfrm.cxx:548
void CheckCharRectAndTopOfLine(const bool _bCheckForParaPorInf)
check anchor character rectangle and top of line
Base class of the Writer layout elements.
Definition: frame.hxx:315
static bool lcl_DoesVertPosFits(const SwTwips _nRelPosY, const SwTwips _nAvail, const SwLayoutFrame *_pUpperOfOrientFrame, const bool _bBrowse, const bool _bGrowInTable, SwLayoutFrame *&_orpLayoutFrameToGrow)
const SwRect & GetLastCharRect() const
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
virtual SwRect GetObjRect() const =0
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:565
bool IsInDocBody() const
Definition: frame.hxx:944
Header in the document layout, inside a page.
Definition: hffrm.hxx:43
SwTwips Grow(SwTwips, bool bTst=false, bool bInfo=false)
Definition: wsfrm.cxx:1503
sal_uInt16 GetLower() const
bool IsInSct() const
Definition: frame.hxx:968
const SwLayoutFrame & GetVertEnvironmentLayoutFrame(const SwFrame &_rVertOrientFrame) const
determine environment layout frame for possible vertical object positions respectively for alignments...
tools::Long BottomDist(const SwRect &rRect, tools::Long nPos) const
Definition: frame.hxx:1415
void CalcOverlap(const SwTextFrame *pAnchorFrameForVertPos, Point &rRelPos, const SwTwips nTopOfAnch)
In case overlap is not allowed, re-position the current object.
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:106
void Left(const tools::Long nLeft)
Definition: swrect.hxx:194
void Refresh(const SwFrame *pFrame)
Definition: frame.hxx:1360
bool IsInFootnote() const
Definition: frame.hxx:950
SwRectFn FnRect() const
Definition: frame.hxx:1370
tools::Long GetRight() const
const SwRect & getFramePrintArea() const
Definition: frame.hxx:181
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:46
bool IsVert() const
Definition: frame.hxx:1368
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
bool IsFootnoteFrame() const
Definition: frame.hxx:1203
constexpr TypedWhichId< SwFlyFrameFormat > RES_FLYFRMFMT(156)
tools::Long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1378
SwRect GetPaintArea() const
|* The paintarea is the area, in which the content of a frame is allowed |* to be displayed...
Definition: ssfrm.cxx:589
void SetCurrRelPos(Point _aRelPos)
bool IsMoveable(const SwLayoutFrame *_pLayoutFrame=nullptr) const
determine, if frame is moveable in given environment
Definition: findfrm.cxx:1362
const SwRect & getFrameArea() const
Definition: frame.hxx:180
bool getBrowseMode() const
Definition: viewopt.hxx:472
bool IsInTab() const
Definition: frame.hxx:956
bool IsTextFrame() const
Definition: frame.hxx:1235
void Width(tools::Long nNew)
Definition: swrect.hxx:186
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
void SetOverlapVertOffset(SwTwips nOverlapVertOffset)
bool IsSctFrame() const
Definition: frame.hxx:1215
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:855
void SetObjTop(const SwTwips _nTop)
static SwFrameFormat * getOtherTextBoxFormat(const SwFrameFormat *pFormat, sal_uInt16 nType, SdrObject *pObject=nullptr)
If we have an associated TextFrame, then return that.
bool IsColumnFrame() const
Definition: frame.hxx:1183
virtual void CalcPosition() override
calculate position of object
SwTwips AdjustVertRelPos(const SwTwips nTopOfAnch, const bool bVert, const bool bVertL2R, const SwFrame &rPageAlignLayFrame, const SwTwips nProposedRelPosY, const bool bFollowTextFlow, const bool bCheckBottom=true) const
adjust calculated vertical in order to keep object inside 'page' alignment layout frame...
Style of a layout element.
Definition: frmfmt.hxx:59
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1269
bool IsContentFrame() const
Definition: frame.hxx:1231
SwFrame * GetIndPrev() const
Definition: frame.hxx:725
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
tools::Long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1411
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:108
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
SwPageFrame * FindPageFrame()
Definition: frame.hxx:681
static bool isTextBox(const SwFrameFormat *pFormat, sal_uInt16 nType, SdrObject *pObject=nullptr)
Is the frame format a text box?
const SwFrame * Lower() const
Definition: layfrm.hxx:101
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1383
FlyAnchors.
Definition: fmtanchr.hxx:34
SwTwips CalcRelPosX(const SwFrame &_rHoriOrientFrame, const SwEnvironmentOfAnchoredObject &_rEnvOfObj, const SwFormatHoriOrient &_rHoriOrient, const SvxLRSpaceItem &_rLRSpacing, const SvxULSpaceItem &_rULSpacing, const bool _bObjWrapThrough, const SwTwips _nRelPosY, SwTwips &_roHoriOffsetToFrameAnchorPos) const
calculate relative horizontal position
tools::Long GetLeft() const
sal_uInt8 GetHeightPercent() const
Definition: fmtfsize.hxx:88
SwLayoutFrame * GetUpper()
Definition: frame.hxx:679
tools::Long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1410
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
tools::Long GetTopMargin(const SwFrame &rFrame) const
Definition: frame.hxx:1404
SwRect PrtWithoutHeaderAndFooter() const
Definition: frmtool.cxx:3864
tools::Long YDiff(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1424
A page of the document layout.
Definition: pagefrm.hxx:57
tools::Long SwTwips
Definition: swtypes.hxx:52
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1116
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
tools::Long const nTopMargin
SwLayoutFrame * GetLeaf(MakePageType eMakePage, bool bFwd)
Definition: flowfrm.cxx:843
MakePageType
Definition: frame.hxx:113
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:423
SwTwips GetLastTopOfLine() const
void Top(const tools::Long nTop)
Definition: swrect.hxx:203
bool IsVertL2R() const
Definition: frame.hxx:1369
void GetVertAlignmentValues(const SwFrame &_rVertOrientFrame, const SwFrame &_rPageAlignLayFrame, const sal_Int16 _eRelOrient, SwTwips &_orAlignAreaHeight, SwTwips &_orAlignAreaOffset) const
const SwFormatWrapInfluenceOnObjPos & GetWrapInfluenceOnObjPos(bool=true) const
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:727
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
tools::Long GetTopMargin() const
Definition: ssfrm.cxx:41
SwTwips GetTopForObjPos(const SwFrame &_rFrame, const SwRectFn &_fnRect, const bool _bVert) const
helper method to determine top of a frame for the vertical object positioning
void SetObjLeft(const SwTwips _nLeft)
tools::Long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1379
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
const SwFrame & GetHoriVirtualAnchor(const SwLayoutFrame &_pProposedFrame) const
determine frame for horizontal position
const SwHeaderFrame * GetHeaderFrame() const
Definition: pagechg.cxx:2550
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:207
bool IsFooterFrame() const
Definition: frame.hxx:1195
SwRootFrame * getRootFrame()
Definition: frame.hxx:680
sal_uInt16 GetUpper() const
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1100
SwFrame * GetNext()
Definition: frame.hxx:677
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74