1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_wasm_strip.h>
22 #include <pagefrm.hxx>
23 #include <rootfrm.hxx>
25 #include <dflyobj.hxx>
26 #include <dcontact.hxx>
29 #include <frmtool.hxx>
30 #include <sectfrm.hxx>
31 #include <notxtfrm.hxx>
34 #include <svx/svdpage.hxx>
35 #include <editeng/ulspitem.hxx>
36 #include <fmtornt.hxx>
37 #include <fmtfsize.hxx>
40 #include <flyfrms.hxx>
41 #include <fmtfollowtextflow.hxx>
42 #include <environmentofanchoredobject.hxx>
43 #include <sortedobjs.hxx>
44 #include <viewimp.hxx>
45 #include <IDocumentSettingAccess.hxx>
46 #include <IDocumentDrawModelAccess.hxx>
48 #include <ndindex.hxx>
49 #include <basegfx/matrix/b2dhommatrixtools.hxx>
50 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
51 #include <osl/diagnose.h>
53 using namespace ::com::sun::star
;
55 SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat
*pFormat
, SwFrame
* pSib
, SwFrame
*pAnch
, bool bFollow
)
56 : SwFlyFrame( pFormat
, pSib
, pAnch
, bFollow
),
60 mbNoMoveOnCheckClip( false )
64 void SwFlyFreeFrame::DestroyImpl()
66 // #i28701# - use new method <GetPageFrame()>
69 if( GetFormat()->GetDoc()->IsInDtor() )
71 // #i29879# - remove also to-frame anchored Writer
72 // fly frame from page.
73 const bool bRemoveFromPage
=
74 GetPageFrame()->GetSortedObjs() &&
75 ( IsFlyAtContentFrame() ||
76 ( GetAnchorFrame() && GetAnchorFrame()->IsFlyFrame() ) );
77 if ( bRemoveFromPage
)
79 GetPageFrame()->GetSortedObjs()->Remove( *this );
84 SwRect
aTmp( GetObjRectWithSpaces() );
85 SwFlyFreeFrame::NotifyBackground( GetPageFrame(), aTmp
, PrepareHint::FlyFrameLeave
);
89 SwFlyFrame::DestroyImpl();
92 SwFlyFreeFrame::~SwFlyFreeFrame()
95 // we are possibly in ContourCache, make sure we vanish
96 ::ClrContourCache(GetVirtDrawObj());
101 /** Notifies the background (all ContentFrames that currently are overlapping).
103 * Additionally, the window is also directly invalidated (especially where
104 * there are no overlapping ContentFrames).
105 * This also takes ContentFrames within other Flys into account.
107 void SwFlyFreeFrame::NotifyBackground( SwPageFrame
*pPageFrame
,
108 const SwRect
& rRect
, PrepareHint eHint
)
110 ::Notify_Background( GetVirtDrawObj(), pPageFrame
, rRect
, eHint
, true );
113 void SwFlyFreeFrame::MakeAll(vcl::RenderContext
* /*pRenderContext*/)
115 if ( !GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
120 if ( !GetAnchorFrame() || IsLocked() || IsColLocked() )
125 // #i28701# - use new method <GetPageFrame()>
126 if( !GetPageFrame() && GetAnchorFrame()->IsInFly() )
128 SwFlyFrame
* pFly
= AnchorFrame()->FindFlyFrame();
129 SwPageFrame
*pPageFrame
= pFly
? pFly
->FindPageFrame() : nullptr;
131 pPageFrame
->AppendFlyToPage( this );
134 if( !GetPageFrame() )
139 Lock(); // The curtain drops
141 // takes care of the notification in the dtor
142 const SwFlyNotify
aNotify( this );
146 setFrameAreaSizeValid(false);
147 m_bHeightClipped
= m_bWidthClipped
= false;
148 // no invalidation of position,
149 // if anchored object is anchored inside a Writer fly frame,
150 // its position is already locked, and it follows the text flow.
151 // #i34753# - add condition:
152 // no invalidation of position, if no direct move is requested in <CheckClip(..)>
153 if ( !IsNoMoveOnCheckClip() &&
154 !( PositionLocked() &&
155 GetAnchorFrame()->IsInFly() &&
156 GetFrameFormat().GetFollowTextFlow().GetValue() ) )
158 setFrameAreaPositionValid(false);
162 // #i81146# new loop control
163 int nLoopControlRuns
= 0;
164 const int nLoopControlMax
= 10;
166 // RotateFlyFrame3 - outer frame
167 const double fRotation(getLocalFrameRotation());
168 const bool bRotated(!basegfx::fTools::equalZero(fRotation
));
172 // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags),
173 // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is
174 // needed. Reset to BoundAreas will be done below automatically
175 if(isTransformableSwFrame())
177 getTransformableSwFrame()->restoreFrameAreas();
181 while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() || m_bFormatHeightOnly
|| !m_bValidContentPos
)
183 SwRectFnSet
aRectFnSet(this);
184 const SwFormatFrameSize
*pSz
;
185 { // Additional scope, so aAccess will be destroyed before the check!
187 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), this );
188 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
189 pSz
= &rAttrs
.GetAttrSet().GetFrameSize();
191 // Only set when the flag is set!
192 if ( !isFrameAreaSizeValid() )
194 setFramePrintAreaValid(false);
197 if ( !isFramePrintAreaValid() )
199 MakePrtArea( rAttrs
);
200 m_bValidContentPos
= false;
203 if ( !isFrameAreaSizeValid() || m_bFormatHeightOnly
)
205 setFrameAreaSizeValid(false);
206 Format( getRootFrame()->GetCurrShell()->GetOut(), &rAttrs
);
207 m_bFormatHeightOnly
= false;
211 if ( !isFrameAreaPositionValid() )
213 const Point
aOldPos( aRectFnSet
.GetPos(getFrameArea()) );
214 // #i26791# - use new method <MakeObjPos()>
215 // #i34753# - no positioning, if requested.
218 setFrameAreaPositionValid(true);
221 // #i26791# - use new method <MakeObjPos()>
223 if (!IsForceNotifyNewBackground() && aOldPos
== aRectFnSet
.GetPos(getFrameArea()))
225 if( !isFrameAreaPositionValid() && GetAnchorFrame()->IsInSct() &&
226 !GetAnchorFrame()->FindSctFrame()->isFrameAreaDefinitionValid() )
228 setFrameAreaPositionValid(true);
233 setFrameAreaSizeValid(false);
237 if ( !m_bValidContentPos
)
239 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), this );
240 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
241 MakeContentPos( rAttrs
);
244 if ( isFrameAreaPositionValid() && isFrameAreaSizeValid() )
248 OSL_ENSURE( nLoopControlRuns
< nLoopControlMax
, "LoopControl in SwFlyFreeFrame::MakeAll" );
250 if ( nLoopControlRuns
< nLoopControlMax
)
254 nLoopControlRuns
= 0;
257 // RotateFlyFrame3 - outer frame
258 // Do not refresh transforms/Areas self here, this will be done
259 // when inner and outer frame are layouted, in SwNoTextFrame::MakeAll
262 // RotateFlyFrame3: Safe changes locally
263 // get center from outer frame (layout frame) to be on the safe side
264 const Point
aCenter(getFrameArea().Center());
265 const basegfx::B2DPoint
aB2DCenter(aCenter
.X(), aCenter
.Y());
267 if(!mpTransformableSwFrame
)
269 mpTransformableSwFrame
.reset(new TransformableSwFrame(*this));
272 getTransformableSwFrame()->createFrameAreaTransformations(
275 getTransformableSwFrame()->adaptFrameAreasToTransformations();
279 // RotateFlyFrame3: Also need to clear ContourCache (if used),
280 // usually done in SwFlyFrame::NotifyDrawObj, but there relies on
281 // being in transform mode which is already reset then
282 if(isTransformableSwFrame())
284 ::ClrContourCache(GetVirtDrawObj());
287 // reset transformations to show that they are not used
288 mpTransformableSwFrame
.reset();
293 #if OSL_DEBUG_LEVEL > 0
294 SwRectFnSet
aRectFnSet(this);
295 OSL_ENSURE( m_bHeightClipped
|| ( aRectFnSet
.GetHeight(getFrameArea()) > 0 &&
296 aRectFnSet
.GetHeight(getFramePrintArea()) > 0),
297 "SwFlyFreeFrame::Format(), flipping Fly." );
302 bool SwFlyFreeFrame::supportsAutoContour() const
304 static bool bOverrideHandleContourToAlwaysOff(true); // loplugin:constvars:ignore
306 // RotateFlyFrameFix: For LO6.0 we need to deactivate the AutoContour feature again, it is simply
307 // not clear how/if to use and save/load it in ODF. This has to be discussed.
308 // The reason not to remove is that this may be used as-is now, using a new switch.
309 // Even when not, the detection if it is possible will be needed in any case later.
310 if(bOverrideHandleContourToAlwaysOff
)
315 if(!isTransformableSwFrame())
317 // support only when transformed, else there is no free space
321 // Check for Borders. If we have Borders, do (currently) not support,
322 // since borders do not transform with the object.
323 // (Will need to be enhanced to take into account if we have Borders and if these
324 // transform with the object)
325 SwBorderAttrAccess
aAccess(SwFrame::GetCache(), this);
326 const SwBorderAttrs
&rAttrs(*aAccess
.Get());
333 // Check for Padding. Do not support when padding is used, this will
334 // produce a covered space around the object (filled with fill defines)
335 const SvxBoxItem
* pBoxItem(nullptr);
337 if(GetFormat() && (pBoxItem
= GetFormat()->GetItemIfSet(RES_BOX
, false)))
339 if(pBoxItem
->HasBorder(/*bTreatPaddingAsBorder*/true))
345 // check for Fill - if we have fill, it will fill the gaps and we will not
346 // support AutoContour
347 if(GetFormat() && GetFormat()->supportsFullDrawingLayerFillAttributeSet())
349 const drawinglayer::attribute::SdrAllFillAttributesHelperPtr
aFillAttributes(GetFormat()->getSdrAllFillAttributesHelper());
351 if(aFillAttributes
&& aFillAttributes
->isUsed())
358 const std::unique_ptr
<SvxBrushItem
> aBack(GetFormat()->makeBackgroundBrushItem());
370 // RotateFlyFrame3 - Support for Transformations - outer frame
371 basegfx::B2DHomMatrix
SwFlyFreeFrame::getFrameAreaTransformation() const
373 if(isTransformableSwFrame())
375 // use pre-created transformation
376 return getTransformableSwFrame()->getLocalFrameAreaTransformation();
380 return SwFlyFrame::getFrameAreaTransformation();
383 basegfx::B2DHomMatrix
SwFlyFreeFrame::getFramePrintAreaTransformation() const
385 if(isTransformableSwFrame())
387 // use pre-created transformation
388 return getTransformableSwFrame()->getLocalFramePrintAreaTransformation();
392 return SwFlyFrame::getFramePrintAreaTransformation();
395 // RotateFlyFrame3 - Support for Transformations
396 void SwFlyFreeFrame::transform_translate(const Point
& rOffset
)
398 // call parent - this will do the basic transform for SwRect(s)
399 // in the SwFrameAreaDefinition
400 SwFlyFrame::transform_translate(rOffset
);
402 // check if the Transformations need to be adapted
403 if(isTransformableSwFrame())
405 const basegfx::B2DHomMatrix
aTransform(
406 basegfx::utils::createTranslateB2DHomMatrix(
407 rOffset
.X(), rOffset
.Y()));
409 // transform using TransformableSwFrame
410 getTransformableSwFrame()->transform(aTransform
);
414 // RotateFlyFrame3 - outer frame
415 double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame
& rNoTextFrame
)
417 return rNoTextFrame
.getLocalFrameRotation();
420 double SwFlyFreeFrame::getLocalFrameRotation() const
422 // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower()
423 // calls SwLayoutFrame::Lower() when it's a SwLayoutFrame - so use GetLower()
424 const SwNoTextFrame
* pSwNoTextFrame(dynamic_cast< const SwNoTextFrame
* >(GetLower()));
426 if(nullptr != pSwNoTextFrame
)
428 return getLocalFrameRotation_from_SwNoTextFrame(*pSwNoTextFrame
);
435 /** determines, if direct environment of fly frame has 'auto' size
438 start with anchor frame and search via <GetUpper()> for a header, footer,
439 row or fly frame stopping at page frame.
440 return <true>, if such a frame is found and it has 'auto' size.
441 otherwise <false> is returned.
443 @return boolean indicating, that direct environment has 'auto' size
445 bool SwFlyFreeFrame::HasEnvironmentAutoSize() const
447 bool bRetVal
= false;
449 const SwFrame
* pToBeCheckedFrame
= GetAnchorFrame();
450 while ( pToBeCheckedFrame
&&
451 !pToBeCheckedFrame
->IsPageFrame() )
453 if ( pToBeCheckedFrame
->IsHeaderFrame() ||
454 pToBeCheckedFrame
->IsFooterFrame() ||
455 pToBeCheckedFrame
->IsRowFrame() ||
456 pToBeCheckedFrame
->IsFlyFrame() )
458 bRetVal
= SwFrameSize::Fixed
!=
459 pToBeCheckedFrame
->GetAttrSet()->GetFrameSize().GetHeightSizeType();
464 pToBeCheckedFrame
= pToBeCheckedFrame
->GetUpper();
471 void SwFlyFreeFrame::CheckClip( const SwFormatFrameSize
&rSz
)
473 // It's probably time now to take appropriate measures, if the Fly
474 // doesn't fit into its surrounding.
475 // First, the Fly gives up its position, then it's formatted.
476 // Only if it still doesn't fit after giving up its position, the
477 // width or height are given up as well. The frame will be squeezed
478 // as much as needed.
480 const SwVirtFlyDrawObj
*pObj
= GetVirtDrawObj();
481 SwRect aClip
, aTmpStretch
;
482 ::CalcClipRect( pObj
, aClip
);
483 ::CalcClipRect( pObj
, aTmpStretch
, false );
484 aClip
.Intersection_( aTmpStretch
);
486 const tools::Long nBot
= getFrameArea().Top() + getFrameArea().Height();
487 const tools::Long nRig
= getFrameArea().Left() + getFrameArea().Width();
488 const tools::Long nClipBot
= aClip
.Top() + aClip
.Height();
489 const tools::Long nClipRig
= aClip
.Left() + aClip
.Width();
491 const bool bBot
= nBot
> nClipBot
;
492 const bool bRig
= nRig
> nClipRig
;
493 if (( bBot
|| bRig
) && !IsDraggingOffPageAllowed(FindFrameFormat(GetDrawObj())))
496 // #i37068# - no move, if it's requested
497 if ( bBot
&& !IsNoMoveOnCheckClip() &&
498 !GetDrawObjs() && !GetAnchorFrame()->IsInTab() )
500 SwFrame
* pHeader
= FindFooterOrHeader();
501 // In a header, correction of the position is no good idea.
502 // If the fly moves, some paragraphs have to be formatted, this
503 // could cause a change of the height of the headerframe,
504 // now the flyframe can change its position and so on ...
505 if ( !pHeader
|| !pHeader
->IsHeaderFrame() )
507 const tools::Long nOld
= getFrameArea().Top();
509 // tdf#112443 disable positioning if content is completely off page
510 bool bDisableOffPagePositioning
= GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING
);
511 if ( !bDisableOffPagePositioning
|| nOld
<= nClipBot
)
513 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
514 aFrm
.Pos().setY( std::max( aClip
.Top(), nClipBot
- aFrm
.Height() ) );
517 if ( getFrameArea().Top() != nOld
)
522 m_bHeightClipped
= true;
527 const tools::Long nOld
= getFrameArea().Left();
529 // tdf#112443 disable positioning if content is completely off page
530 bool bDisableOffPagePositioning
= GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING
);
531 if ( !bDisableOffPagePositioning
|| nOld
<= nClipRig
)
533 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
534 aFrm
.Pos().setX( std::max( aClip
.Left(), nClipRig
- aFrm
.Width() ) );
537 if ( getFrameArea().Left() != nOld
)
539 const SwFormatHoriOrient
&rH
= GetFormat()->GetHoriOrient();
540 // Left-aligned ones may not be moved to the left when they
541 // are avoiding another one.
542 if( rH
.GetHoriOrient() == text::HoriOrientation::LEFT
)
544 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
545 aFrm
.Pos().setX( nOld
);
552 m_bWidthClipped
= true;
556 setFrameAreaSizeValid(false);
560 // If we reach this branch, the Frame protrudes into forbidden
561 // areas, and correcting the position is not allowed or not
562 // possible or not required.
564 // For Flys with OLE objects as lower, we make sure that
565 // we always resize proportionally
566 Size
aOldSize( getFrameArea().SSize() );
568 // First, setup the FrameRect, then transfer it to the Frame.
569 SwRect
aFrameRect( getFrameArea() );
573 tools::Long nDiff
= nClipBot
;
574 nDiff
-= aFrameRect
.Top(); // nDiff represents the available distance
575 nDiff
= aFrameRect
.Height() - nDiff
;
576 aFrameRect
.Height( aFrameRect
.Height() - nDiff
);
577 m_bHeightClipped
= true;
581 tools::Long nDiff
= nClipRig
;
582 nDiff
-= aFrameRect
.Left();// nDiff represents the available distance
583 nDiff
= aFrameRect
.Width() - nDiff
;
584 aFrameRect
.Width( aFrameRect
.Width() - nDiff
);
585 m_bWidthClipped
= true;
588 // #i17297# - no proportional
589 // scaling of graphics in environments, which determines its size
590 // by its content ('auto' size). Otherwise layout loops can occur and
591 // layout sizes of the environment can be incorrect.
592 // Such environment are:
593 // (1) header and footer frames with 'auto' size
594 // (2) table row frames with 'auto' size
595 // (3) fly frames with 'auto' size
596 // Note: section frames seems to be not critical - didn't found
597 // any critical layout situation so far.
598 if ( Lower() && Lower()->IsNoTextFrame() &&
599 (static_cast<SwNoTextFrame
*>(Lower())->GetNode()->GetOLENode() ||
600 !HasEnvironmentAutoSize() ) )
602 // If width and height got adjusted, then the bigger
603 // change is relevant.
604 if ( aFrameRect
.Width() != aOldSize
.Width() &&
605 aFrameRect
.Height()!= aOldSize
.Height() )
607 if ( (aOldSize
.Width() - aFrameRect
.Width()) >
608 (aOldSize
.Height()- aFrameRect
.Height()) )
609 aFrameRect
.Height( aOldSize
.Height() );
611 aFrameRect
.Width( aOldSize
.Width() );
614 // Adjusted the width? change height proportionally
615 if( aFrameRect
.Width() != aOldSize
.Width() )
617 aFrameRect
.Height( aFrameRect
.Width() * aOldSize
.Height() /
619 m_bHeightClipped
= true;
621 // Adjusted the height? change width proportionally
622 else if( aFrameRect
.Height() != aOldSize
.Height() )
624 aFrameRect
.Width( aFrameRect
.Height() * aOldSize
.Width() /
626 m_bWidthClipped
= true;
629 // #i17297# - reactivate change
630 // of size attribute for fly frames containing an ole object.
632 // Added the aFrameRect.HasArea() hack, because
633 // the environment of the ole object does not have to be valid
634 // at this moment, or even worse, it does not have to have a
635 // reasonable size. In this case we do not want to change to
636 // attributes permanently. Maybe one day somebody dares to remove
638 if ( aFrameRect
.HasArea() &&
639 static_cast<SwNoTextFrame
*>(Lower())->GetNode()->GetOLENode() &&
640 ( m_bWidthClipped
|| m_bHeightClipped
) )
642 SwFlyFrameFormat
*pFormat
= GetFormat();
643 pFormat
->LockModify();
644 SwFormatFrameSize
aFrameSize( rSz
);
645 aFrameSize
.SetWidth( aFrameRect
.Width() );
646 aFrameSize
.SetHeight( aFrameRect
.Height() );
647 pFormat
->SetFormatAttr( aFrameSize
);
648 pFormat
->UnlockModify();
652 // Now change the Frame; for columns, we put the new values into the attributes,
653 // otherwise we'll end up with unwanted side-effects/oscillations
654 const tools::Long nPrtHeightDiff
= getFrameArea().Height() - getFramePrintArea().Height();
655 const tools::Long nPrtWidthDiff
= getFrameArea().Width() - getFramePrintArea().Width();
656 maUnclippedFrame
= getFrameArea();
659 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
660 aFrm
.Height( aFrameRect
.Height() );
661 aFrm
.Width ( std::max( tools::Long(MINLAY
), aFrameRect
.Width() ) );
664 if ( Lower() && Lower()->IsColumnFrame() )
666 ColLock(); //lock grow/shrink
667 const Size
aTmpOldSize( getFramePrintArea().SSize() );
670 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
671 aPrt
.Height( getFrameArea().Height() - nPrtHeightDiff
);
672 aPrt
.Width ( getFrameArea().Width() - nPrtWidthDiff
);
675 ChgLowersProp( aTmpOldSize
);
676 SwFrame
*pLow
= Lower();
679 pLow
->Calc(getRootFrame()->GetCurrShell()->GetOut());
680 // also calculate the (Column)BodyFrame
681 static_cast<SwLayoutFrame
*>(pLow
)->Lower()->Calc(getRootFrame()->GetCurrShell()->GetOut());
682 pLow
= pLow
->GetNext();
684 ::CalcContent( this );
687 if ( !isFrameAreaSizeValid() && !m_bWidthClipped
)
689 setFrameAreaSizeValid(true);
690 m_bFormatHeightOnly
= true;
695 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
696 aPrt
.Height( getFrameArea().Height() - nPrtHeightDiff
);
697 aPrt
.Width ( getFrameArea().Width() - nPrtWidthDiff
);
703 OSL_ENSURE( getFrameArea().Height() >= 0,
704 "<SwFlyFreeFrame::CheckClip(..)> - fly frame has negative height now." );
707 /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
710 bool SwFlyFreeFrame::IsFormatPossible() const
712 return SwFlyFrame::IsFormatPossible() &&
714 ( GetAnchorFrame() && GetAnchorFrame()->IsInFly() ) );
717 SwFlyLayFrame::SwFlyLayFrame( SwFlyFrameFormat
*pFormat
, SwFrame
* pSib
, SwFrame
*pAnch
) :
718 SwFlyFreeFrame( pFormat
, pSib
, pAnch
)
723 void SwFlyLayFrame::RegisterAtPage(SwPageFrame
& rPageFrame
)
725 assert(GetPageFrame() != &rPageFrame
);
728 GetPageFrame()->MoveFly( this, &rPageFrame
);
732 rPageFrame
.AppendFlyToPage( this );
738 void SwFlyLayFrame::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
740 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
742 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
745 const auto pAnch
= GetAnchorFromPoolItem(*pLegacy
->m_pNew
);
749 SwFlyFrame::SwClientNotify(rMod
, rHint
);
752 SAL_WARN_IF(pAnch
->GetAnchorId() == GetFormat()->GetAnchor().GetAnchorId(), "sw.core", "Invalid change of anchor type.");
754 // Unregister, get hold of the page, attach to the corresponding LayoutFrame.
755 SwRect
aOld(GetObjRectWithSpaces());
756 // #i28701# - use new method <GetPageFrame()>
757 SwPageFrame
* pOldPage
= GetPageFrame();
758 AnchorFrame()->RemoveFly(this);
760 if(RndStdIds::FLY_AT_PAGE
== pAnch
->GetAnchorId())
762 SwRootFrame
* pRoot
= getRootFrame();
763 SwPageFrame
* pTmpPage
= static_cast<SwPageFrame
*>(pRoot
->Lower());
764 sal_uInt16 nPagesToFlip
= pAnch
->GetPageNum()-1;
765 while(pTmpPage
&& nPagesToFlip
)
767 pTmpPage
= static_cast<SwPageFrame
*>(pTmpPage
->GetNext());
770 if(pTmpPage
&& !nPagesToFlip
)
772 // #i50432# - adjust synopsis of <PlaceFly(..)>
773 pTmpPage
->PlaceFly(this, nullptr);
777 pRoot
->SetAssertFlyPages();
778 pRoot
->AssertFlyPages();
783 SwNodeIndex
aIdx(*pAnch
->GetAnchorNode());
784 SwContentFrame
* pContent
= GetFormat()->GetDoc()->GetNodes().GoNext(&aIdx
)->
785 GetContentNode()->getLayoutFrame(getRootFrame(), nullptr, nullptr);
788 SwFlyFrame
*pTmp
= pContent
->FindFlyFrame();
790 pTmp
->AppendFly(this);
793 // #i28701# - use new method <GetPageFrame()>
794 if ( pOldPage
&& pOldPage
!= GetPageFrame() )
795 NotifyBackground( pOldPage
, aOld
, PrepareHint::FlyFrameLeave
);
801 void SwPageFrame::AppendFlyToPage( SwFlyFrame
*pNew
)
803 if ( !pNew
->GetVirtDrawObj()->IsInserted() )
804 getRootFrame()->GetDrawPage()->InsertObject(
805 static_cast<SdrObject
*>(pNew
->GetVirtDrawObj()),
806 pNew
->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
808 InvalidateSpelling();
809 InvalidateSmartTags();
810 InvalidateAutoCompleteWords();
811 InvalidateWordCount();
815 static_cast<SwRootFrame
*>(GetUpper())->SetIdleFlags();
816 static_cast<SwRootFrame
*>(GetUpper())->InvalidateBrowseWidth();
819 SdrObject
* pObj
= pNew
->GetVirtDrawObj();
820 OSL_ENSURE( pNew
->GetAnchorFrame(), "Fly without Anchor" );
821 SwFlyFrame
* pFly
= const_cast<SwFlyFrame
*>(pNew
->GetAnchorFrame()->FindFlyFrame());
822 if ( pFly
&& pObj
->GetOrdNum() < pFly
->GetVirtDrawObj()->GetOrdNum() )
824 //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
825 sal_uInt32 nNewNum
= pObj
->GetOrdNumDirect();
826 SdrObject
* pDrawObj
= nullptr;
827 if (auto pFormat
= pFly
->GetFormat())
828 if (auto pShapeFormat
= SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_FLYFRMFMT
))
829 pDrawObj
= pShapeFormat
->FindRealSdrObject();
833 if (auto pPage
= pDrawObj
->getSdrPageFromSdrObject())
834 pPage
->SetObjectOrdNum(pDrawObj
->GetOrdNumDirect(), nNewNum
);
836 pDrawObj
->SetOrdNum(nNewNum
);
839 if ( pObj
->getSdrPageFromSdrObject() )
840 pObj
->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly
->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum
+ (pDrawObj
? 1 : 0) );
842 pFly
->GetVirtDrawObj()->SetOrdNum( nNewNum
+ (pDrawObj
? 1 : 0));
845 // Don't look further at Flys that sit inside the Content.
846 if ( pNew
->IsFlyInContentFrame() )
847 InvalidateFlyInCnt();
850 InvalidateFlyContent();
852 if ( !m_pSortedObjs
)
854 m_pSortedObjs
.reset(new SwSortedObjs());
857 const bool bSuccessInserted
= m_pSortedObjs
->Insert( *pNew
);
858 OSL_ENSURE( bSuccessInserted
, "Fly not inserted in Sorted." );
861 OSL_ENSURE( pNew
->GetPageFrame() == nullptr || pNew
->GetPageFrame() == this,
862 "<SwPageFrame::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect." );
863 // #i28701# - use new method <SetPageFrame(..)>
864 pNew
->SetPageFrame( this );
865 pNew
->InvalidatePage( this );
867 pNew
->UnlockPosition();
868 // needed to reposition at-page anchored flys moved from different page
869 pNew
->InvalidateObjPos();
871 // Notify accessible layout. That's required at this place for
872 // frames only where the anchor is moved. Creation of new frames
873 // is additionally handled by the SwFrameNotify class.
874 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
876 static_cast< SwRootFrame
* >( GetUpper() )->IsAnyShellAccessible() &&
877 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell() )
879 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell()->Imp()
880 ->AddAccessibleFrame( pNew
);
885 // #i28701# - correction: consider also drawing objects
886 if ( !pNew
->GetDrawObjs() )
889 SwSortedObjs
&rObjs
= *pNew
->GetDrawObjs();
890 for (SwAnchoredObject
* pTmpObj
: rObjs
)
892 if ( auto pTmpFly
= pTmpObj
->DynCastFlyFrame() )
894 // #i28701# - use new method <GetPageFrame()>
895 if ( pTmpFly
->IsFlyFreeFrame() && !pTmpFly
->GetPageFrame() )
896 AppendFlyToPage( pTmpFly
);
898 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pTmpObj
) != nullptr )
901 if ( pTmpObj
->GetPageFrame() != this )
903 if ( pTmpObj
->GetPageFrame() != nullptr )
905 pTmpObj
->GetPageFrame()->RemoveDrawObjFromPage( *pTmpObj
);
907 AppendDrawObjToPage( *pTmpObj
);
913 void SwPageFrame::RemoveFlyFromPage( SwFlyFrame
*pToRemove
)
915 const sal_uInt32 nOrdNum
= pToRemove
->GetVirtDrawObj()->GetOrdNum();
916 getRootFrame()->GetDrawPage()->RemoveObject( nOrdNum
);
917 pToRemove
->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum
);
921 if ( !pToRemove
->IsFlyInContentFrame() )
922 static_cast<SwRootFrame
*>(GetUpper())->SetSuperfluous();
923 static_cast<SwRootFrame
*>(GetUpper())->InvalidateBrowseWidth();
926 // Don't look further at Flys that sit inside the Content.
927 if ( pToRemove
->IsFlyInContentFrame() )
930 // Don't delete collections just yet. This will happen at the end of the
931 // action in the RemoveSuperfluous of the page, kicked off by a method of
932 // the same name in the root.
933 // The FlyColl might be gone already, because the page's dtor is being
935 // Remove it _before_ disposing accessible frames to avoid accesses to
936 // the Frame from event handlers.
939 m_pSortedObjs
->Remove(*pToRemove
);
940 if (!m_pSortedObjs
->size())
942 m_pSortedObjs
.reset();
946 // Notify accessible layout. That's required at this place for
947 // frames only where the anchor is moved. Creation of new frames
948 // is additionally handled by the SwFrameNotify class.
949 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
951 static_cast< SwRootFrame
* >( GetUpper() )->IsAnyShellAccessible() &&
952 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell() )
954 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell()->Imp()
955 ->DisposeAccessibleFrame( pToRemove
, true );
959 // #i28701# - use new method <SetPageFrame(..)>
960 pToRemove
->SetPageFrame( nullptr );
963 void SwPageFrame::MoveFly( SwFlyFrame
*pToMove
, SwPageFrame
*pDest
)
968 static_cast<SwRootFrame
*>(GetUpper())->SetIdleFlags();
969 if ( !pToMove
->IsFlyInContentFrame() && pDest
->GetPhyPageNum() < GetPhyPageNum() )
970 static_cast<SwRootFrame
*>(GetUpper())->SetSuperfluous();
973 pDest
->InvalidateSpelling();
974 pDest
->InvalidateSmartTags();
975 pDest
->InvalidateAutoCompleteWords();
976 pDest
->InvalidateWordCount();
978 if ( pToMove
->IsFlyInContentFrame() )
980 pDest
->InvalidateFlyInCnt();
984 // Notify accessible layout. That's required at this place for
985 // frames only where the anchor is moved. Creation of new frames
986 // is additionally handled by the SwFrameNotify class.
987 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
989 static_cast< SwRootFrame
* >( GetUpper() )->IsAnyShellAccessible() &&
990 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell() )
992 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell()->Imp()
993 ->DisposeAccessibleFrame( pToMove
, true );
997 // The FlyColl might be gone already, because the page's dtor is being executed.
1000 m_pSortedObjs
->Remove( *pToMove
);
1001 if ( !m_pSortedObjs
->size() )
1003 m_pSortedObjs
.reset();
1006 // Removing a fly from the page affects the margin of tables, so update the frame print area
1007 // of the lowers of my body frame.
1008 SwFrame
* pBodyFrame
= FindBodyCont();
1011 for (SwFrame
* pFrame
= pBodyFrame
->GetLower(); pFrame
; pFrame
= pFrame
->GetNext())
1013 if (!pFrame
->IsTabFrame())
1015 // This is meant to match SwTabFrame::CalcFlyOffsets(), so not relevant for
1016 // other frame types.
1020 pFrame
->InvalidatePrt();
1026 if ( !pDest
->GetSortedObjs() )
1027 pDest
->m_pSortedObjs
.reset(new SwSortedObjs());
1029 const bool bSuccessInserted
= pDest
->GetSortedObjs()->Insert( *pToMove
);
1030 OSL_ENSURE( bSuccessInserted
, "Fly not inserted in Sorted." );
1032 // #i28701# - use new method <SetPageFrame(..)>
1033 pToMove
->SetPageFrame( pDest
);
1034 pToMove
->InvalidatePage( pDest
);
1035 pToMove
->SetNotifyBack();
1036 pDest
->InvalidateFlyContent();
1038 pToMove
->UnlockPosition();
1040 // Notify accessible layout. That's required at this place for
1041 // frames only where the anchor is moved. Creation of new frames
1042 // is additionally handled by the SwFrameNotify class.
1043 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1045 static_cast< SwRootFrame
* >( GetUpper() )->IsAnyShellAccessible() &&
1046 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell() )
1048 static_cast< SwRootFrame
* >( GetUpper() )->GetCurrShell()->Imp()
1049 ->AddAccessibleFrame( pToMove
);
1053 // #i28701# - correction: move lowers of Writer fly frame
1054 if ( !pToMove
->GetDrawObjs() )
1057 SwSortedObjs
&rObjs
= *pToMove
->GetDrawObjs();
1058 for (SwAnchoredObject
* pObj
: rObjs
)
1060 if ( auto pFly
= pObj
->DynCastFlyFrame() )
1062 if ( pFly
->IsFlyFreeFrame() )
1064 // #i28701# - use new method <GetPageFrame()>
1065 SwPageFrame
* pPageFrame
= pFly
->GetPageFrame();
1067 pPageFrame
->MoveFly( pFly
, pDest
);
1069 pDest
->AppendFlyToPage( pFly
);
1072 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
1074 RemoveDrawObjFromPage( *pObj
);
1075 pDest
->AppendDrawObjToPage( *pObj
);
1080 void SwPageFrame::AppendDrawObjToPage( SwAnchoredObject
& _rNewObj
)
1082 if ( dynamic_cast<const SwAnchoredDrawObject
*>( &_rNewObj
) == nullptr )
1084 OSL_FAIL( "SwPageFrame::AppendDrawObjToPage(..) - anchored object of unexpected type -> object not appended" );
1090 static_cast<SwRootFrame
*>(GetUpper())->InvalidateBrowseWidth();
1093 assert(_rNewObj
.GetAnchorFrame());
1094 SwFlyFrame
* pFlyFrame
= const_cast<SwFlyFrame
*>(_rNewObj
.GetAnchorFrame()->FindFlyFrame());
1096 _rNewObj
.GetDrawObj()->GetOrdNum() < pFlyFrame
->GetVirtDrawObj()->GetOrdNum() )
1098 //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
1099 sal_uInt32 nNewNum
= _rNewObj
.GetDrawObj()->GetOrdNumDirect();
1100 if ( _rNewObj
.GetDrawObj()->getSdrPageFromSdrObject() )
1101 _rNewObj
.DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFlyFrame
->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum
);
1103 pFlyFrame
->GetVirtDrawObj()->SetOrdNum( nNewNum
);
1106 if ( RndStdIds::FLY_AS_CHAR
== _rNewObj
.GetFrameFormat().GetAnchor().GetAnchorId() )
1111 if ( !m_pSortedObjs
)
1113 m_pSortedObjs
.reset(new SwSortedObjs());
1115 if ( !m_pSortedObjs
->Insert( _rNewObj
) )
1117 OSL_ENSURE( m_pSortedObjs
->Contains( _rNewObj
),
1118 "Drawing object not appended into list <pSortedObjs>." );
1121 OSL_ENSURE( _rNewObj
.GetPageFrame() == nullptr || _rNewObj
.GetPageFrame() == this,
1122 "<SwPageFrame::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect." );
1123 _rNewObj
.SetPageFrame( this );
1125 // invalidate page in order to force a reformat of object layout of the page.
1126 InvalidateFlyLayout();
1129 void SwPageFrame::RemoveDrawObjFromPage( SwAnchoredObject
& _rToRemoveObj
)
1131 if ( dynamic_cast<const SwAnchoredDrawObject
*>( &_rToRemoveObj
) == nullptr )
1133 OSL_FAIL( "SwPageFrame::RemoveDrawObjFromPage(..) - anchored object of unexpected type -> object not removed" );
1137 if ( m_pSortedObjs
)
1139 m_pSortedObjs
->Remove( _rToRemoveObj
);
1140 if ( !m_pSortedObjs
->size() )
1142 m_pSortedObjs
.reset();
1146 if (RndStdIds::FLY_AS_CHAR
!=
1147 _rToRemoveObj
.GetFrameFormat().GetAnchor().GetAnchorId())
1149 static_cast<SwRootFrame
*>(GetUpper())->SetSuperfluous();
1152 static_cast<SwRootFrame
*>(GetUpper())->InvalidateBrowseWidth();
1155 _rToRemoveObj
.SetPageFrame( nullptr );
1158 // #i50432# - adjust method description and synopsis.
1159 void SwPageFrame::PlaceFly( SwFlyFrame
* pFly
, SwFlyFrameFormat
* pFormat
)
1161 // #i50432# - consider the case that page is an empty page:
1162 // In this case append the fly frame at the next page
1163 OSL_ENSURE( !IsEmptyPage() || GetNext(),
1164 "<SwPageFrame::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" );
1165 if ( IsEmptyPage() && GetNext() )
1167 static_cast<SwPageFrame
*>(GetNext())->PlaceFly( pFly
, pFormat
);
1171 // If we received a Fly, we use that one. Otherwise, create a new
1172 // one using the Format.
1177 OSL_ENSURE( pFormat
, ":-( No Format given for Fly." );
1178 pFly
= new SwFlyLayFrame( pFormat
, this, this );
1180 ::RegistFlys( this, pFly
);
1185 // #i18732# - adjustments for following text flow or not
1186 // AND alignment at 'page areas' for to paragraph/to character anchored objects
1187 // #i22305# - adjustment for following text flow for to frame anchored objects
1188 // #i29778# - Because calculating the floating screen object's position
1189 // (Writer fly frame or drawing object) doesn't perform a calculation on its
1190 // upper frames and its anchor frame, a calculation of the upper frames in this
1191 // method is no longer sensible.
1192 // #i28701# - if document compatibility option 'Consider wrapping style influence
1193 // on object positioning' is ON, the clip area corresponds to the one as the
1194 // object doesn't follow the text flow.
1195 bool CalcClipRect( const SdrObject
*pSdrObj
, SwRect
&rRect
, bool bMove
)
1198 if ( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>(pSdrObj
) )
1200 const SwFlyFrame
* pFly
= pVirtFlyDrawObj
->GetFlyFrame();
1201 const bool bFollowTextFlow
= pFly
->GetFormat()->GetFollowTextFlow().GetValue();
1203 const bool bConsiderWrapOnObjPos
=
1204 pFly
->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
);
1205 const SwFormatVertOrient
&rV
= pFly
->GetFormat()->GetVertOrient();
1206 if( pFly
->IsFlyLayFrame() )
1208 const SwFrame
* pClip
;
1211 if ( !bFollowTextFlow
|| bConsiderWrapOnObjPos
)
1213 pClip
= pFly
->GetAnchorFrame()->FindPageFrame();
1217 pClip
= pFly
->GetAnchorFrame();
1220 rRect
= pClip
->getFrameArea();
1221 SwRectFnSet
aRectFnSet(pClip
);
1223 // vertical clipping: Top and Bottom, also to PrtArea if necessary
1224 if( rV
.GetVertOrient() != text::VertOrientation::NONE
&&
1225 rV
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
)
1227 aRectFnSet
.SetTop( rRect
, aRectFnSet
.GetPrtTop(*pClip
) );
1228 aRectFnSet
.SetBottom( rRect
, aRectFnSet
.GetPrtBottom(*pClip
) );
1230 // horizontal clipping: Top and Bottom, also to PrtArea if necessary
1231 const SwFormatHoriOrient
&rH
= pFly
->GetFormat()->GetHoriOrient();
1232 if( rH
.GetHoriOrient() != text::HoriOrientation::NONE
&&
1233 rH
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
)
1235 aRectFnSet
.SetLeft( rRect
, aRectFnSet
.GetPrtLeft(*pClip
) );
1236 aRectFnSet
.SetRight(rRect
, aRectFnSet
.GetPrtRight(*pClip
));
1239 else if( pFly
->IsFlyAtContentFrame() )
1241 // #i18732# - consider following text flow or not
1242 // AND alignment at 'page areas'
1243 const SwFrame
* pVertPosOrientFrame
= pFly
->GetVertPosOrientFrame();
1244 if ( !pVertPosOrientFrame
)
1246 OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
1247 pVertPosOrientFrame
= pFly
->GetAnchorFrame();
1250 if ( !bFollowTextFlow
|| bConsiderWrapOnObjPos
)
1252 const SwLayoutFrame
* pClipFrame
= pVertPosOrientFrame
->FindPageFrame();
1255 OSL_FAIL("!pClipFrame: "
1256 "if you can reproduce this please file a bug");
1259 rRect
= bMove
? pClipFrame
->GetUpper()->getFrameArea()
1260 : pClipFrame
->getFrameArea();
1261 // #i26945# - consider that a table, during
1262 // its format, can exceed its upper printing area bottom.
1263 // Thus, enlarge the clip rectangle, if such a case occurred
1264 if ( pFly
->GetAnchorFrame()->IsInTab() )
1266 const SwTabFrame
* pTabFrame
= const_cast<SwFlyFrame
*>(pFly
)
1267 ->GetAnchorFrameContainingAnchPos()->FindTabFrame();
1268 SwRect
aTmp( pTabFrame
->getFramePrintArea() );
1269 aTmp
+= pTabFrame
->getFrameArea().Pos();
1270 rRect
.Union( aTmp
);
1271 // #i43913# - consider also the cell frame
1272 const SwFrame
* pCellFrame
= const_cast<SwFlyFrame
*>(pFly
)
1273 ->GetAnchorFrameContainingAnchPos()->GetUpper();
1274 while ( pCellFrame
&& !pCellFrame
->IsCellFrame() )
1276 pCellFrame
= pCellFrame
->GetUpper();
1280 aTmp
= pCellFrame
->getFramePrintArea();
1281 aTmp
+= pCellFrame
->getFrameArea().Pos();
1282 rRect
.Union( aTmp
);
1286 else if ( rV
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
||
1287 rV
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
)
1289 // new class <SwEnvironmentOfAnchoredObject>
1290 objectpositioning::SwEnvironmentOfAnchoredObject
1291 aEnvOfObj( bFollowTextFlow
);
1292 const SwLayoutFrame
& rVertClipFrame
=
1293 aEnvOfObj
.GetVertEnvironmentLayoutFrame( *pVertPosOrientFrame
);
1294 if ( rV
.GetRelationOrient() == text::RelOrientation::PAGE_FRAME
)
1296 rRect
= rVertClipFrame
.getFrameArea();
1298 else if ( rV
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
)
1300 if ( rVertClipFrame
.IsPageFrame() )
1302 rRect
= static_cast<const SwPageFrame
&>(rVertClipFrame
).PrtWithoutHeaderAndFooter();
1306 rRect
= rVertClipFrame
.getFrameArea();
1309 const SwLayoutFrame
* pHoriClipFrame
=
1310 pFly
->GetAnchorFrame()->FindPageFrame()->GetUpper();
1311 SwRectFnSet
aRectFnSet(pFly
->GetAnchorFrame());
1312 aRectFnSet
.SetLeft( rRect
, aRectFnSet
.GetLeft(pHoriClipFrame
->getFrameArea()) );
1313 aRectFnSet
.SetRight(rRect
, aRectFnSet
.GetRight(pHoriClipFrame
->getFrameArea()));
1318 const SwFrame
*pClip
=
1319 const_cast<SwFlyFrame
*>(pFly
)->GetAnchorFrameContainingAnchPos();
1320 SwRectFnSet
aRectFnSet(pClip
);
1321 const SwLayoutFrame
*pUp
= pClip
->GetUpper();
1322 const SwFrame
*pCell
= pUp
->IsCellFrame() ? pUp
: nullptr;
1323 const SwFrameType nType
= bMove
1324 ? SwFrameType::Root
| SwFrameType::Fly
| SwFrameType::Header
|
1325 SwFrameType::Footer
| SwFrameType::Ftn
1326 : SwFrameType::Body
| SwFrameType::Fly
| SwFrameType::Header
|
1327 SwFrameType::Footer
| SwFrameType::Cell
| SwFrameType::Ftn
;
1329 while ( !(pUp
->GetType() & nType
) || pUp
->IsColBodyFrame() )
1331 pUp
= pUp
->GetUpper();
1332 if ( !pCell
&& pUp
->IsCellFrame() )
1335 if ( bMove
&& pUp
->IsRootFrame() )
1337 rRect
= pUp
->getFramePrintArea();
1338 rRect
+= pUp
->getFrameArea().Pos();
1343 if ( pUp
->GetType() & SwFrameType::Body
)
1345 const SwPageFrame
*pPg
;
1346 if ( pUp
->GetUpper() != (pPg
= pFly
->FindPageFrame()) )
1347 pUp
= pPg
->FindBodyCont();
1350 rRect
= pUp
->GetUpper()->getFrameArea();
1351 aRectFnSet
.SetTop( rRect
, aRectFnSet
.GetPrtTop(*pUp
) );
1352 aRectFnSet
.SetBottom(rRect
, aRectFnSet
.GetPrtBottom(*pUp
));
1357 if( ( pUp
->GetType() & (SwFrameType::Fly
| SwFrameType::Ftn
) ) &&
1358 !pUp
->getFrameArea().Contains( pFly
->getFrameArea().Pos() ) )
1360 if( pUp
->IsFlyFrame() )
1362 const SwFlyFrame
*pTmpFly
= static_cast<const SwFlyFrame
*>(pUp
);
1363 while( pTmpFly
->GetNextLink() )
1365 pTmpFly
= pTmpFly
->GetNextLink();
1366 if( pTmpFly
->getFrameArea().Contains( pFly
->getFrameArea().Pos() ) )
1371 else if( pUp
->IsInFootnote() )
1373 const SwFootnoteFrame
*pTmp
= pUp
->FindFootnoteFrame();
1374 while( pTmp
->GetFollow() )
1376 pTmp
= pTmp
->GetFollow();
1377 if( pTmp
->getFrameArea().Contains( pFly
->getFrameArea().Pos() ) )
1383 rRect
= pUp
->getFramePrintArea();
1384 rRect
.Pos() += pUp
->getFrameArea().Pos();
1385 if ( pUp
->GetType() & (SwFrameType::Header
| SwFrameType::Footer
) )
1387 rRect
.Left ( pUp
->GetUpper()->getFrameArea().Left() );
1388 rRect
.Width( pUp
->GetUpper()->getFrameArea().Width());
1390 else if ( pUp
->IsCellFrame() ) //MA_FLY_HEIGHT
1392 const SwFrame
*pTab
= pUp
->FindTabFrame();
1393 aRectFnSet
.SetBottom( rRect
, aRectFnSet
.GetPrtBottom(*pTab
->GetUpper()) );
1394 // expand to left and right cell border
1395 rRect
.Left ( pUp
->getFrameArea().Left() );
1396 rRect
.Width( pUp
->getFrameArea().Width() );
1402 // CellFrames might also sit in unallowed areas. In this case,
1403 // the Fly is allowed to do so as well
1404 SwRect
aTmp( pCell
->getFramePrintArea() );
1405 aTmp
+= pCell
->getFrameArea().Pos();
1406 rRect
.Union( aTmp
);
1412 const SwFrame
*pUp
= pFly
->GetAnchorFrame()->GetUpper();
1413 SwRectFnSet
aRectFnSet(pFly
->GetAnchorFrame());
1414 while( pUp
->IsColumnFrame() || pUp
->IsSctFrame() || pUp
->IsColBodyFrame())
1415 pUp
= pUp
->GetUpper();
1416 rRect
= pUp
->getFrameArea();
1417 if( !pUp
->IsBodyFrame() )
1419 rRect
+= pUp
->getFramePrintArea().Pos();
1420 rRect
.SSize( pUp
->getFramePrintArea().SSize() );
1421 if ( pUp
->IsCellFrame() )
1423 const SwFrame
*pTab
= pUp
->FindTabFrame();
1424 aRectFnSet
.SetBottom( rRect
, aRectFnSet
.GetPrtBottom(*pTab
->GetUpper()) );
1427 else if ( pUp
->GetUpper()->IsPageFrame() )
1429 // Objects anchored as character may exceed right margin
1431 aRectFnSet
.SetRight( rRect
, aRectFnSet
.GetRight(pUp
->GetUpper()->getFrameArea()) );
1433 tools::Long nHeight
= (9*aRectFnSet
.GetHeight(rRect
))/10;
1435 const SwFormat
*pFormat
= GetUserCall(pSdrObj
)->GetFormat();
1436 const SvxULSpaceItem
&rUL
= pFormat
->GetULSpace();
1439 nTop
= aRectFnSet
.IsVert() ? static_cast<const SwFlyInContentFrame
*>(pFly
)->GetRefPoint().X() :
1440 static_cast<const SwFlyInContentFrame
*>(pFly
)->GetRefPoint().Y();
1441 nTop
= aRectFnSet
.YInc( nTop
, -nHeight
);
1442 tools::Long nWidth
= aRectFnSet
.GetWidth(pFly
->getFrameArea());
1443 aRectFnSet
.SetLeftAndWidth( rRect
, aRectFnSet
.IsVert() ?
1444 static_cast<const SwFlyInContentFrame
*>(pFly
)->GetRefPoint().Y() :
1445 static_cast<const SwFlyInContentFrame
*>(pFly
)->GetRefPoint().X(), nWidth
);
1446 nHeight
= 2*nHeight
- rUL
.GetLower() - rUL
.GetUpper();
1450 nTop
= aRectFnSet
.YInc( aRectFnSet
.GetBottom(pFly
->getFrameArea()),
1451 rUL
.GetLower() - nHeight
);
1452 nHeight
= 2*nHeight
- aRectFnSet
.GetHeight(pFly
->getFrameArea())
1453 - rUL
.GetLower() - rUL
.GetUpper();
1455 aRectFnSet
.SetTopAndHeight( rRect
, nTop
, nHeight
);
1460 const SwDrawContact
*pC
= static_cast<const SwDrawContact
*>(GetUserCall(pSdrObj
));
1461 const SwFrameFormat
*pFormat
= pC
->GetFormat();
1462 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1463 if ( RndStdIds::FLY_AS_CHAR
== rAnch
.GetAnchorId() )
1465 const SwFrame
* pAnchorFrame
= pC
->GetAnchorFrame( pSdrObj
);
1468 OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." );
1469 const_cast<SwDrawContact
*>(pC
)->ConnectToLayout();
1470 pAnchorFrame
= pC
->GetAnchorFrame();
1472 const SwFrame
* pUp
= pAnchorFrame
->GetUpper();
1473 rRect
= pUp
->getFramePrintArea();
1474 rRect
+= pUp
->getFrameArea().Pos();
1475 SwRectFnSet
aRectFnSet(pAnchorFrame
);
1476 tools::Long nHeight
= (9*aRectFnSet
.GetHeight(rRect
))/10;
1478 const SvxULSpaceItem
&rUL
= pFormat
->GetULSpace();
1479 SwRect
aSnapRect( pSdrObj
->GetSnapRect() );
1480 tools::Long nTmpH
= 0;
1483 nTop
= aRectFnSet
.YInc( aRectFnSet
.IsVert() ? pSdrObj
->GetAnchorPos().X() :
1484 pSdrObj
->GetAnchorPos().Y(), -nHeight
);
1485 tools::Long nWidth
= aRectFnSet
.GetWidth(aSnapRect
);
1486 aRectFnSet
.SetLeftAndWidth( rRect
, aRectFnSet
.IsVert() ?
1487 pSdrObj
->GetAnchorPos().Y() :
1488 pSdrObj
->GetAnchorPos().X(), nWidth
);
1492 // #i26791# - value of <nTmpH> is needed to
1493 // calculate value of <nTop>.
1494 nTmpH
= aRectFnSet
.IsVert() ? pSdrObj
->GetCurrentBoundRect().GetWidth() :
1495 pSdrObj
->GetCurrentBoundRect().GetHeight();
1496 nTop
= aRectFnSet
.YInc( aRectFnSet
.GetTop(aSnapRect
),
1497 rUL
.GetLower() + nTmpH
- nHeight
);
1499 nHeight
= 2*nHeight
- nTmpH
- rUL
.GetLower() - rUL
.GetUpper();
1500 aRectFnSet
.SetTopAndHeight( rRect
, nTop
, nHeight
);
1504 // restrict clip rectangle for drawing
1505 // objects in header/footer to the page frame.
1507 const SwFrame
* pAnchorFrame
= pC
->GetAnchorFrame( pSdrObj
);
1508 if ( pAnchorFrame
&& pAnchorFrame
->FindFooterOrHeader() )
1510 // clip frame is the page frame the header/footer is on.
1511 const SwFrame
* pClipFrame
= pAnchorFrame
->FindPageFrame();
1512 rRect
= pClipFrame
->getFrameArea();
1523 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */