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