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