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