Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sw / source / core / layout / fly.cxx
blob74a2f6201e4b9bd34aa6a32a96b932361fb056c3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svl/itemiter.hxx>
21 #include <svtools/imap.hxx>
22 #include <tools/helpers.hxx>
23 #include <editeng/protitem.hxx>
24 #include <editeng/opaqitem.hxx>
25 #include <editeng/ulspitem.hxx>
26 #include <editeng/frmdiritem.hxx>
27 #include <drawdoc.hxx>
28 #include <fmtfsize.hxx>
29 #include <fmtclds.hxx>
30 #include <fmtcntnt.hxx>
31 #include <fmturl.hxx>
32 #include <fmtsrnd.hxx>
33 #include <fmtornt.hxx>
34 #include <fmtcnct.hxx>
35 #include <ndgrf.hxx>
36 #include <tolayoutanchoredobjectposition.hxx>
37 #include <fmtfollowtextflow.hxx>
38 #include <sortedobjs.hxx>
39 #include <objectformatter.hxx>
40 #include <ndole.hxx>
41 #include <swtable.hxx>
42 #include <svx/svdpage.hxx>
43 #include <svx/svdoashp.hxx>
44 #include <layouter.hxx>
45 #include <pagefrm.hxx>
46 #include <rootfrm.hxx>
47 #include <viewimp.hxx>
48 #include <viewopt.hxx>
49 #include <dcontact.hxx>
50 #include <dflyobj.hxx>
51 #include <dview.hxx>
52 #include <frmtool.hxx>
53 #include <hints.hxx>
54 #include <tabfrm.hxx>
55 #include <txtfrm.hxx>
56 #include <notxtfrm.hxx>
57 #include <flyfrms.hxx>
58 #include <sectfrm.hxx>
59 #include <vcl/svapp.hxx>
60 #include <calbck.hxx>
61 #include <IDocumentSettingAccess.hxx>
62 #include <IDocumentLayoutAccess.hxx>
63 #include <textboxhelper.hxx>
64 #include <txtfly.hxx>
65 #include <ndindex.hxx>
66 #include <pam.hxx>
67 #include <basegfx/polygon/b2dpolygontools.hxx>
68 #include <basegfx/matrix/b2dhommatrixtools.hxx>
70 using namespace ::com::sun::star;
72 static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame );
74 SwFlyFrame::SwFlyFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) :
75 SwLayoutFrame( pFormat, pSib ),
76 SwAnchoredObject(), // #i26791#
77 m_pPrevLink( nullptr ),
78 m_pNextLink( nullptr ),
79 m_bInCnt( false ),
80 m_bAtCnt( false ),
81 m_bLayout( false ),
82 m_bAutoPosition( false ),
83 m_bValidContentPos( false )
85 mnFrameType = SwFrameType::Fly;
87 m_bInvalid = m_bNotifyBack = true;
88 m_bLocked = m_bMinHeight =
89 m_bHeightClipped = m_bWidthClipped = m_bFormatHeightOnly = false;
91 // Size setting: Fixed size is always the width
92 const SwFormatFrameSize &rFrameSize = pFormat->GetFrameSize();
93 const SvxFrameDirection nDir = pFormat->GetFormatAttr( RES_FRAMEDIR ).GetValue();
94 if( SvxFrameDirection::Environment == nDir )
96 mbDerivedVert = true;
97 mbDerivedR2L = true;
99 else
101 mbInvalidVert = false;
102 mbDerivedVert = false;
103 mbDerivedR2L = false;
104 if( SvxFrameDirection::Horizontal_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir )
106 mbVertLR = false;
107 mbVertical = false;
109 else
111 const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
112 if( pSh && pSh->GetViewOptions()->getBrowseMode() )
114 mbVertLR = false;
115 mbVertical = false;
117 else
119 mbVertical = true;
121 if ( SvxFrameDirection::Vertical_LR_TB == nDir )
122 mbVertLR = true;
123 else
124 mbVertLR = false;
128 mbInvalidR2L = false;
129 if( SvxFrameDirection::Horizontal_RL_TB == nDir )
130 mbRightToLeft = true;
131 else
132 mbRightToLeft = false;
136 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
137 aFrm.Width( rFrameSize.GetWidth() );
138 aFrm.Height( rFrameSize.GetHeightSizeType() == ATT_VAR_SIZE ? MINFLY : rFrameSize.GetHeight() );
141 // Fixed or variable Height?
142 if ( rFrameSize.GetHeightSizeType() == ATT_MIN_SIZE )
143 m_bMinHeight = true;
144 else if ( rFrameSize.GetHeightSizeType() == ATT_FIX_SIZE )
145 mbFixSize = true;
147 // insert columns, if necessary
148 InsertColumns();
150 // First the Init, then the Content:
151 // This is due to the fact that the Content may have Objects/Frames,
152 // which are then registered
153 InitDrawObj();
155 Chain( pAnch );
157 InsertCnt();
159 // Put it somewhere outside so that out document is not formatted unnecessarily often
160 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
161 aFrm.Pos().setX(FAR_AWAY);
162 aFrm.Pos().setY(FAR_AWAY);
165 void SwFlyFrame::Chain( SwFrame* _pAnch )
167 // Connect to chain neighbours.
168 // No problem, if a neighboor doesn't exist - the construction of the
169 // neighboor will make the connection
170 const SwFormatChain& rChain = GetFormat()->GetChain();
171 if ( rChain.GetPrev() || rChain.GetNext() )
173 if ( rChain.GetNext() )
175 SwFlyFrame* pFollow = FindChainNeighbour( *rChain.GetNext(), _pAnch );
176 if ( pFollow )
178 OSL_ENSURE( !pFollow->GetPrevLink(), "wrong chain detected" );
179 if ( !pFollow->GetPrevLink() )
180 SwFlyFrame::ChainFrames( this, pFollow );
183 if ( rChain.GetPrev() )
185 SwFlyFrame *pMaster = FindChainNeighbour( *rChain.GetPrev(), _pAnch );
186 if ( pMaster )
188 OSL_ENSURE( !pMaster->GetNextLink(), "wrong chain detected" );
189 if ( !pMaster->GetNextLink() )
190 SwFlyFrame::ChainFrames( pMaster, this );
196 void SwFlyFrame::InsertCnt()
198 if ( !GetPrevLink() )
200 const SwFormatContent& rContent = GetFormat()->GetContent();
201 OSL_ENSURE( rContent.GetContentIdx(), ":-( no content prepared." );
202 sal_uLong nIndex = rContent.GetContentIdx()->GetIndex();
203 // Lower() means SwColumnFrame; the Content then needs to be inserted into the (Column)BodyFrame
204 ::InsertCnt_( Lower() ? static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(Lower())->Lower()) : static_cast<SwLayoutFrame*>(this),
205 GetFormat()->GetDoc(), nIndex );
207 // NoText always have a fixed height.
208 if ( Lower() && Lower()->IsNoTextFrame() )
210 mbFixSize = true;
211 m_bMinHeight = false;
216 void SwFlyFrame::InsertColumns()
218 // #i97379#
219 // Check, if column are allowed.
220 // Columns are not allowed for fly frames, which represent graphics or embedded objects.
221 const SwFormatContent& rContent = GetFormat()->GetContent();
222 OSL_ENSURE( rContent.GetContentIdx(), "<SwFlyFrame::InsertColumns()> - no content prepared." );
223 SwNodeIndex aFirstContent( *(rContent.GetContentIdx()), 1 );
224 if ( aFirstContent.GetNode().IsNoTextNode() )
226 return;
229 const SwFormatCol &rCol = GetFormat()->GetCol();
230 if ( rCol.GetNumCols() > 1 )
232 // Start off PrtArea to be as large as Frame, so that we can put in the columns
233 // properly. It'll adjust later on.
235 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
236 aPrt.Width( getFrameArea().Width() );
237 aPrt.Height( getFrameArea().Height() );
240 const SwFormatCol aOld; // ChgColumns() also needs an old value passed
241 ChgColumns( aOld, rCol );
245 void SwFlyFrame::DestroyImpl()
247 // Accessible objects for fly frames will be destroyed in this destructor.
248 // For frames bound as char or frames that don't have an anchor we have
249 // to do that ourselves. For any other frame the call RemoveFly at the
250 // anchor will do that.
251 if( IsAccessibleFrame() && GetFormat() && (IsFlyInContentFrame() || !GetAnchorFrame()) )
253 SwRootFrame *pRootFrame = getRootFrame();
254 if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
256 SwViewShell *pVSh = pRootFrame->GetCurrShell();
257 if( pVSh && pVSh->Imp() )
259 // Lowers aren't disposed already, so we have to do a recursive
260 // dispose
261 pVSh->Imp()->DisposeAccessibleFrame( this, true );
266 if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() )
268 // OD 2004-01-19 #110582#
269 Unchain();
271 // OD 2004-01-19 #110582#
272 DeleteCnt();
274 if ( GetAnchorFrame() )
275 AnchorFrame()->RemoveFly( this );
278 FinitDrawObj();
280 SwLayoutFrame::DestroyImpl();
283 SwFlyFrame::~SwFlyFrame()
287 const IDocumentDrawModelAccess& SwFlyFrame::getIDocumentDrawModelAccess()
289 return GetFormat()->getIDocumentDrawModelAccess();
292 // OD 2004-01-19 #110582#
293 void SwFlyFrame::Unchain()
295 if ( GetPrevLink() )
296 UnchainFrames( GetPrevLink(), this );
297 if ( GetNextLink() )
298 UnchainFrames( this, GetNextLink() );
301 // OD 2004-01-19 #110582#
302 void SwFlyFrame::DeleteCnt()
304 SwFrame* pFrame = m_pLower;
305 while ( pFrame )
307 while ( pFrame->GetDrawObjs() && pFrame->GetDrawObjs()->size() )
309 SwAnchoredObject *pAnchoredObj = (*pFrame->GetDrawObjs())[0];
310 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) != nullptr )
312 SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj));
314 else if ( dynamic_cast<const SwAnchoredDrawObject*>( pAnchoredObj) != nullptr )
316 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
317 SdrObject* pObj = pAnchoredObj->DrawObj();
318 if ( dynamic_cast<const SwDrawVirtObj*>( pObj) != nullptr )
320 SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pObj);
321 pDrawVirtObj->RemoveFromWriterLayout();
322 pDrawVirtObj->RemoveFromDrawingPage();
324 else
326 SwDrawContact* pContact =
327 static_cast<SwDrawContact*>(::GetUserCall( pObj ));
328 if ( pContact )
330 pContact->DisconnectFromLayout();
336 pFrame->RemoveFromLayout();
337 SwFrame::DestroyFrame(pFrame);
338 pFrame = m_pLower;
341 InvalidatePage();
344 void SwFlyFrame::InitDrawObj()
346 // OD 2004-03-22 #i26791#
347 SetDrawObj(*SwFlyDrawContact::CreateNewRef(this, GetFormat()));
349 // Set the right Layer
350 // OD 2004-01-19 #110582#
351 IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
352 SdrLayerID nHeavenId = rIDDMA.GetHeavenId();
353 SdrLayerID nHellId = rIDDMA.GetHellId();
354 // OD 2004-03-22 #i26791#
355 GetVirtDrawObj()->SetLayer( GetFormat()->GetOpaque().GetValue()
356 ? nHeavenId
357 : nHellId );
360 void SwFlyFrame::FinitDrawObj()
362 if(!GetVirtDrawObj() )
363 return;
364 SwFormat* pFormat = GetFormat();
365 // Deregister from SdrPageViews if the Objects is still selected there.
366 if(!pFormat->GetDoc()->IsInDtor())
368 SwViewShell* p1St = getRootFrame()->GetCurrShell();
369 if(p1St)
371 for(SwViewShell& rCurrentShell : p1St->GetRingContainer())
372 { // At the moment the Drawing can do just do an Unmark on everything,
373 // as the Object was already removed
374 if(rCurrentShell.HasDrawView() )
375 rCurrentShell.Imp()->GetDrawView()->UnmarkAll();
380 // Else calls delete of the ContactObj
381 GetVirtDrawObj()->SetUserCall(nullptr);
383 // Deregisters itself at the Master
384 // always use SdrObject::Free(...) for SdrObjects (!)
385 SdrObject* pTemp(GetVirtDrawObj());
386 SdrObject::Free(pTemp);
389 void SwFlyFrame::ChainFrames( SwFlyFrame *pMaster, SwFlyFrame *pFollow )
391 OSL_ENSURE( pMaster && pFollow, "incomplete chain" );
392 OSL_ENSURE( !pMaster->GetNextLink(), "link can not be changed" );
393 OSL_ENSURE( !pFollow->GetPrevLink(), "link can not be changed" );
395 pMaster->m_pNextLink = pFollow;
396 pFollow->m_pPrevLink = pMaster;
398 if ( pMaster->ContainsContent() )
400 // To get a text flow we need to invalidate
401 SwFrame *pInva = pMaster->FindLastLower();
402 SwRectFnSet aRectFnSet(pMaster);
403 const long nBottom = aRectFnSet.GetPrtBottom(*pMaster);
404 while ( pInva )
406 if( aRectFnSet.BottomDist( pInva->getFrameArea(), nBottom ) <= 0 )
408 pInva->InvalidateSize();
409 pInva->Prepare();
410 pInva = pInva->FindPrev();
412 else
413 pInva = nullptr;
417 if ( pFollow->ContainsContent() )
419 // There's only the content from the Masters left; the content from the Follow
420 // does not have any Frames left (should always be exactly one empty TextNode).
421 SwFrame *pFrame = pFollow->ContainsContent();
422 OSL_ENSURE( !pFrame->IsTabFrame() && !pFrame->FindNext(), "follow in chain contains content" );
423 pFrame->Cut();
424 SwFrame::DestroyFrame(pFrame);
427 // invalidate accessible relation set (accessibility wrapper)
428 SwViewShell* pSh = pMaster->getRootFrame()->GetCurrShell();
429 if( pSh )
431 SwRootFrame* pLayout = pMaster->getRootFrame();
432 if( pLayout && pLayout->IsAnyShellAccessible() )
433 pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
437 void SwFlyFrame::UnchainFrames( SwFlyFrame *pMaster, SwFlyFrame *pFollow )
439 pMaster->m_pNextLink = nullptr;
440 pFollow->m_pPrevLink = nullptr;
442 if ( pFollow->ContainsContent() )
444 // The Master sucks up the content of the Follow
445 SwLayoutFrame *pUpper = pMaster;
446 if ( pUpper->Lower()->IsColumnFrame() )
448 pUpper = static_cast<SwLayoutFrame*>(pUpper->GetLastLower());
449 pUpper = static_cast<SwLayoutFrame*>(pUpper->Lower()); // The (Column)BodyFrame
450 OSL_ENSURE( pUpper && pUpper->IsColBodyFrame(), "Missing ColumnBody" );
452 SwFlyFrame *pFoll = pFollow;
453 while ( pFoll )
455 SwFrame *pTmp = ::SaveContent( pFoll );
456 if ( pTmp )
457 ::RestoreContent( pTmp, pUpper, pMaster->FindLastLower() );
458 pFoll->SetCompletePaint();
459 pFoll->InvalidateSize();
460 pFoll = pFoll->GetNextLink();
464 // The Follow needs his own content to be served
465 const SwFormatContent &rContent = pFollow->GetFormat()->GetContent();
466 OSL_ENSURE( rContent.GetContentIdx(), ":-( No content prepared." );
467 sal_uLong nIndex = rContent.GetContentIdx()->GetIndex();
468 // Lower() means SwColumnFrame: this one contains another SwBodyFrame
469 ::InsertCnt_( pFollow->Lower() ? const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFollow->Lower())->Lower()))
470 : static_cast<SwLayoutFrame*>(pFollow),
471 pFollow->GetFormat()->GetDoc(), ++nIndex );
473 // invalidate accessible relation set (accessibility wrapper)
474 SwViewShell* pSh = pMaster->getRootFrame()->GetCurrShell();
475 if( pSh )
477 SwRootFrame* pLayout = pMaster->getRootFrame();
478 if( pLayout && pLayout->IsAnyShellAccessible() )
479 pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
483 SwFlyFrame *SwFlyFrame::FindChainNeighbour( SwFrameFormat const &rChain, SwFrame *pAnch )
485 // We look for the Fly that's in the same Area.
486 // Areas can for now only be Head/Footer or Flys.
488 if ( !pAnch ) // If an Anchor was passed along, that one counts (ctor!)
489 pAnch = AnchorFrame();
491 SwLayoutFrame *pLay;
492 if ( pAnch->IsInFly() )
493 pLay = pAnch->FindFlyFrame();
494 else
496 // FindFooterOrHeader is not appropriate here, as we may not have a
497 // connection to the Anchor yet.
498 pLay = pAnch->GetUpper();
499 while ( pLay && !(pLay->GetType() & (SwFrameType::Header|SwFrameType::Footer)) )
500 pLay = pLay->GetUpper();
503 SwIterator<SwFlyFrame,SwFormat> aIter( rChain );
504 SwFlyFrame *pFly = aIter.First();
505 if ( pLay )
507 while ( pFly )
509 if ( pFly->GetAnchorFrame() )
511 if ( pFly->GetAnchorFrame()->IsInFly() )
513 if ( pFly->AnchorFrame()->FindFlyFrame() == pLay )
514 break;
516 else if ( pLay == pFly->FindFooterOrHeader() )
517 break;
519 pFly = aIter.Next();
522 else if ( pFly )
524 OSL_ENSURE( !aIter.Next(), "chain with more than one instance" );
526 return pFly;
529 SwFrame *SwFlyFrame::FindLastLower()
531 SwFrame *pRet = ContainsAny();
532 if ( pRet && pRet->IsInTab() )
533 pRet = pRet->FindTabFrame();
534 SwFrame *pNxt = pRet;
535 while ( pNxt && IsAnLower( pNxt ) )
536 { pRet = pNxt;
537 pNxt = pNxt->FindNext();
539 return pRet;
542 bool SwFlyFrame::FrameSizeChg( const SwFormatFrameSize &rFrameSize )
544 bool bRet = false;
545 SwTwips nDiffHeight = getFrameArea().Height();
546 if ( rFrameSize.GetHeightSizeType() == ATT_VAR_SIZE )
547 mbFixSize = m_bMinHeight = false;
548 else
550 if ( rFrameSize.GetHeightSizeType() == ATT_FIX_SIZE )
552 mbFixSize = true;
553 m_bMinHeight = false;
555 else if ( rFrameSize.GetHeightSizeType() == ATT_MIN_SIZE )
557 mbFixSize = false;
558 m_bMinHeight = true;
560 nDiffHeight -= rFrameSize.GetHeight();
562 // If the Fly contains columns, we already need to set the Fly
563 // and the Columns to the required value or else we run into problems.
564 if ( Lower() )
566 if ( Lower()->IsColumnFrame() )
568 const SwRect aOld( GetObjRectWithSpaces() );
569 const Size aOldSz( getFramePrintArea().SSize() );
570 const SwTwips nDiffWidth = getFrameArea().Width() - rFrameSize.GetWidth();
573 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
574 aFrm.Height( aFrm.Height() - nDiffHeight );
575 aFrm.Width ( aFrm.Width() - nDiffWidth );
578 // #i68520#
579 InvalidateObjRectWithSpaces();
582 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
583 aPrt.Height( aPrt.Height() - nDiffHeight );
584 aPrt.Width ( aPrt.Width() - nDiffWidth );
587 ChgLowersProp( aOldSz );
588 ::Notify( this, FindPageFrame(), aOld );
589 setFrameAreaPositionValid(false);
590 bRet = true;
592 else if ( Lower()->IsNoTextFrame() )
594 mbFixSize = true;
595 m_bMinHeight = false;
598 return bRet;
601 void SwFlyFrame::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
603 SwFrame::SwClientNotify(rMod, rHint);
604 if (auto pGetZOrdnerHint = dynamic_cast<const sw::GetZOrderHint*>(&rHint))
606 const auto& rFormat(dynamic_cast<const SwFrameFormat&>(rMod));
607 if (rFormat.Which() == RES_FLYFRMFMT && rFormat.getIDocumentLayoutAccess().GetCurrentViewShell()) // #i11176#
608 pGetZOrdnerHint->m_rnZOrder = GetVirtDrawObj()->GetOrdNum();
610 else if (auto pConnectedHint = dynamic_cast<const sw::GetObjectConnectedHint*>(&rHint))
612 const auto& rFormat(dynamic_cast<const SwFrameFormat&>(rMod));
613 if (!pConnectedHint->m_risConnected && rFormat.Which() == RES_FLYFRMFMT && (!pConnectedHint->m_pRoot || pConnectedHint->m_pRoot == getRootFrame()))
614 pConnectedHint->m_risConnected = true;
618 void SwFlyFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
620 sal_uInt8 nInvFlags = 0;
622 if (pNew && pOld && RES_ATTRSET_CHG == pNew->Which())
624 SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() );
625 SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
626 SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
627 SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
628 while( true )
630 UpdateAttr_( aOIter.GetCurItem(),
631 aNIter.GetCurItem(), nInvFlags,
632 &aOldSet, &aNewSet );
633 if( aNIter.IsAtEnd() )
634 break;
635 aNIter.NextItem();
636 aOIter.NextItem();
638 if ( aOldSet.Count() || aNewSet.Count() )
639 SwLayoutFrame::Modify( &aOldSet, &aNewSet );
641 else
642 UpdateAttr_( pOld, pNew, nInvFlags );
644 if ( nInvFlags == 0 )
645 return;
647 Invalidate_();
648 if ( nInvFlags & 0x01 )
650 InvalidatePos_();
651 // #i68520#
652 InvalidateObjRectWithSpaces();
654 if ( nInvFlags & 0x02 )
656 InvalidateSize_();
657 // #i68520#
658 InvalidateObjRectWithSpaces();
660 if ( nInvFlags & 0x04 )
661 InvalidatePrt_();
662 if ( nInvFlags & 0x08 )
663 SetNotifyBack();
664 if ( nInvFlags & 0x10 )
665 SetCompletePaint();
666 if ( ( nInvFlags & 0x40 ) && Lower() && Lower()->IsNoTextFrame() )
667 ClrContourCache( GetVirtDrawObj() );
668 SwRootFrame *pRoot;
669 if ( nInvFlags & 0x20 && nullptr != (pRoot = getRootFrame()) )
670 pRoot->InvalidateBrowseWidth();
671 // #i28701#
672 if ( nInvFlags & 0x80 )
674 // update sorted object lists, the Writer fly frame is registered at.
675 UpdateObjInSortedList();
678 // #i87645# - reset flags for the layout process (only if something has been invalidated)
679 ResetLayoutProcessBools();
683 void SwFlyFrame::UpdateAttr_( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
684 sal_uInt8 &rInvFlags,
685 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
687 bool bClear = true;
688 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
689 SwViewShell *pSh = getRootFrame()->GetCurrShell();
690 switch( nWhich )
692 case RES_VERT_ORIENT:
693 case RES_HORI_ORIENT:
694 // OD 22.09.2003 #i18732# - consider new option 'follow text flow'
695 case RES_FOLLOW_TEXT_FLOW:
697 // ATTENTION: Always also change Action in ChgRePos()!
698 rInvFlags |= 0x09;
700 break;
701 // OD 2004-07-01 #i28701# - consider new option 'wrap influence on position'
702 case RES_WRAP_INFLUENCE_ON_OBJPOS:
704 rInvFlags |= 0x89;
706 break;
707 case RES_SURROUND:
709 // OD 2004-05-13 #i28701# - invalidate position on change of
710 // wrapping style.
711 //rInvFlags |= 0x40;
712 rInvFlags |= 0x41;
713 // The background needs to be messaged and invalidated
714 const SwRect aTmp( GetObjRectWithSpaces() );
715 NotifyBackground( FindPageFrame(), aTmp, PREP_FLY_ATTR_CHG );
717 // By changing the flow of frame-bound Frames, a vertical alignment
718 // can be activated/deactivated => MakeFlyPos
719 if( RndStdIds::FLY_AT_FLY == GetFormat()->GetAnchor().GetAnchorId() )
720 rInvFlags |= 0x09;
722 // Delete contour in the Node if necessary
723 if ( Lower() && Lower()->IsNoTextFrame() &&
724 !GetFormat()->GetSurround().IsContour() )
726 SwNoTextNode *pNd = static_cast<SwNoTextNode*>(static_cast<SwNoTextFrame*>(Lower())->GetNode());
727 if ( pNd->HasContour() )
728 pNd->SetContour( nullptr );
730 // #i28701# - perform reorder of object lists
731 // at anchor frame and at page frame.
732 rInvFlags |= 0x80;
734 break;
736 case RES_PROTECT:
737 if (pNew)
739 const SvxProtectItem *pP = static_cast<const SvxProtectItem*>(pNew);
740 GetVirtDrawObj()->SetMoveProtect( pP->IsPosProtected() );
741 GetVirtDrawObj()->SetResizeProtect( pP->IsSizeProtected() );
742 if( pSh )
744 SwRootFrame* pLayout = getRootFrame();
745 if( pLayout && pLayout->IsAnyShellAccessible() )
746 pSh->Imp()->InvalidateAccessibleEditableState( true, this );
749 break;
750 case RES_COL:
751 if (pOld && pNew)
753 ChgColumns( *static_cast<const SwFormatCol*>(pOld), *static_cast<const SwFormatCol*>(pNew) );
754 const SwFormatFrameSize &rNew = GetFormat()->GetFrameSize();
755 if ( FrameSizeChg( rNew ) )
756 NotifyDrawObj();
757 rInvFlags |= 0x1A;
759 break;
761 case RES_FRM_SIZE:
762 case RES_FMT_CHG:
764 const SwFormatFrameSize &rNew = GetFormat()->GetFrameSize();
765 if ( FrameSizeChg( rNew ) )
766 NotifyDrawObj();
767 rInvFlags |= 0x7F;
768 if (pOld && RES_FMT_CHG == nWhich)
770 SwRect aNew( GetObjRectWithSpaces() );
771 SwRect aOld( getFrameArea() );
772 const SvxULSpaceItem &rUL = static_cast<const SwFormatChg*>(pOld)->pChangedFormat->GetULSpace();
773 aOld.Top( std::max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
774 aOld.SSize().AdjustHeight(rUL.GetLower() );
775 const SvxLRSpaceItem &rLR = static_cast<const SwFormatChg*>(pOld)->pChangedFormat->GetLRSpace();
776 aOld.Left ( std::max( aOld.Left() - rLR.GetLeft(), 0L ) );
777 aOld.SSize().AdjustWidth(rLR.GetRight() );
778 aNew.Union( aOld );
779 NotifyBackground( FindPageFrame(), aNew, PREP_CLEAR );
781 // Special case:
782 // When assigning a template we cannot rely on the old column
783 // attribute. As there need to be at least enough for ChgColumns,
784 // we need to create a temporary attribute.
785 SwFormatCol aCol;
786 if ( Lower() && Lower()->IsColumnFrame() )
788 sal_uInt16 nCol = 0;
789 SwFrame *pTmp = Lower();
791 { ++nCol;
792 pTmp = pTmp->GetNext();
793 } while ( pTmp );
794 aCol.Init( nCol, 0, 1000 );
796 ChgColumns( aCol, GetFormat()->GetCol() );
799 SwFormatURL aURL( GetFormat()->GetURL() );
801 SwFormatFrameSize *pNewFormatFrameSize = nullptr;
802 SwFormatChg *pOldFormatChg = nullptr;
803 if (nWhich == RES_FRM_SIZE)
804 pNewFormatFrameSize = const_cast<SwFormatFrameSize*>(static_cast<const SwFormatFrameSize*>(pNew));
805 else
806 pOldFormatChg = const_cast<SwFormatChg*>(static_cast<const SwFormatChg*>(pOld));
808 if (aURL.GetMap() && (pNewFormatFrameSize || pOldFormatChg))
810 const SwFormatFrameSize &rOld = pNewFormatFrameSize ?
811 *pNewFormatFrameSize :
812 pOldFormatChg->pChangedFormat->GetFrameSize();
813 //#35091# Can be "times zero", when loading the template
814 if ( rOld.GetWidth() && rOld.GetHeight() )
817 Fraction aScaleX( rOld.GetWidth(), rNew.GetWidth() );
818 Fraction aScaleY( rOld.GetHeight(), rOld.GetHeight() );
819 aURL.GetMap()->Scale( aScaleX, aScaleY );
820 SwFrameFormat *pFormat = GetFormat();
821 pFormat->LockModify();
822 pFormat->SetFormatAttr( aURL );
823 pFormat->UnlockModify();
826 const SvxProtectItem &rP = GetFormat()->GetProtect();
827 GetVirtDrawObj()->SetMoveProtect( rP.IsPosProtected() );
828 GetVirtDrawObj()->SetResizeProtect( rP.IsSizeProtected() );
830 if ( pSh )
831 pSh->InvalidateWindows( getFrameArea() );
832 const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
833 const SdrLayerID nId = GetFormat()->GetOpaque().GetValue() ?
834 rIDDMA.GetHeavenId() :
835 rIDDMA.GetHellId();
836 GetVirtDrawObj()->SetLayer( nId );
838 if ( Lower() )
840 // Delete contour in the Node if necessary
841 if( Lower()->IsNoTextFrame() &&
842 !GetFormat()->GetSurround().IsContour() )
844 SwNoTextNode *pNd = static_cast<SwNoTextNode*>(static_cast<SwNoTextFrame*>(Lower())->GetNode());
845 if ( pNd->HasContour() )
846 pNd->SetContour( nullptr );
848 else if( !Lower()->IsColumnFrame() )
850 SwFrame* pFrame = GetLastLower();
851 if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
852 pFrame->Prepare( PREP_ADJUST_FRM );
856 // #i28701# - perform reorder of object lists
857 // at anchor frame and at page frame.
858 rInvFlags |= 0x80;
860 break;
862 case RES_UL_SPACE:
863 case RES_LR_SPACE:
865 rInvFlags |= 0x41;
866 if( pSh && pSh->GetViewOptions()->getBrowseMode() )
867 getRootFrame()->InvalidateBrowseWidth();
868 SwRect aNew( GetObjRectWithSpaces() );
869 SwRect aOld( getFrameArea() );
870 if (pNew)
872 if ( RES_UL_SPACE == nWhich )
874 const SvxULSpaceItem &rUL = *static_cast<const SvxULSpaceItem*>(pNew);
875 aOld.Top( std::max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
876 aOld.SSize().AdjustHeight(rUL.GetLower() );
878 else
880 const SvxLRSpaceItem &rLR = *static_cast<const SvxLRSpaceItem*>(pNew);
881 aOld.Left ( std::max( aOld.Left() - rLR.GetLeft(), 0L ) );
882 aOld.SSize().AdjustWidth(rLR.GetRight() );
885 aNew.Union( aOld );
886 NotifyBackground( FindPageFrame(), aNew, PREP_CLEAR );
888 break;
890 case RES_TEXT_VERT_ADJUST:
892 InvalidateContentPos();
893 rInvFlags |= 0x10;
895 break;
897 case RES_BOX:
898 case RES_SHADOW:
899 rInvFlags |= 0x17;
900 break;
902 case RES_FRAMEDIR :
903 SetDerivedVert( false );
904 SetDerivedR2L( false );
905 CheckDirChange();
906 break;
908 case RES_OPAQUE:
910 if ( pSh )
911 pSh->InvalidateWindows( getFrameArea() );
913 const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
914 const SdrLayerID nId = static_cast<const SvxOpaqueItem*>(pNew)->GetValue() ?
915 rIDDMA.GetHeavenId() :
916 rIDDMA.GetHellId();
917 GetVirtDrawObj()->SetLayer( nId );
918 if( pSh )
920 SwRootFrame* pLayout = getRootFrame();
921 if( pLayout && pLayout->IsAnyShellAccessible() )
923 pSh->Imp()->DisposeAccessibleFrame( this );
924 pSh->Imp()->AddAccessibleFrame( this );
927 // #i28701# - perform reorder of object lists
928 // at anchor frame and at page frame.
929 rInvFlags |= 0x80;
931 break;
933 case RES_URL:
934 // The interface changes the frame size when interacting with text frames,
935 // the Map, however, needs to be relative to FrameSize().
936 if ( (!Lower() || !Lower()->IsNoTextFrame()) && pNew && pOld &&
937 static_cast<const SwFormatURL*>(pNew)->GetMap() && static_cast<const SwFormatURL*>(pOld)->GetMap() )
939 const SwFormatFrameSize &rSz = GetFormat()->GetFrameSize();
940 if ( rSz.GetHeight() != getFrameArea().Height() ||
941 rSz.GetWidth() != getFrameArea().Width() )
943 SwFormatURL aURL( GetFormat()->GetURL() );
944 Fraction aScaleX( getFrameArea().Width(), rSz.GetWidth() );
945 Fraction aScaleY( getFrameArea().Height(), rSz.GetHeight() );
946 aURL.GetMap()->Scale( aScaleX, aScaleY );
947 SwFrameFormat *pFormat = GetFormat();
948 pFormat->LockModify();
949 pFormat->SetFormatAttr( aURL );
950 pFormat->UnlockModify();
953 // No invalidation necessary
954 break;
956 case RES_CHAIN:
957 if (pNew)
959 const SwFormatChain *pChain = static_cast<const SwFormatChain*>(pNew);
960 if ( pChain->GetNext() )
962 SwFlyFrame *pFollow = FindChainNeighbour( *pChain->GetNext() );
963 if ( GetNextLink() && pFollow != GetNextLink() )
964 SwFlyFrame::UnchainFrames( this, GetNextLink());
965 if ( pFollow )
967 if ( pFollow->GetPrevLink() &&
968 pFollow->GetPrevLink() != this )
969 SwFlyFrame::UnchainFrames( pFollow->GetPrevLink(),
970 pFollow );
971 if ( !GetNextLink() )
972 SwFlyFrame::ChainFrames( this, pFollow );
975 else if ( GetNextLink() )
976 SwFlyFrame::UnchainFrames( this, GetNextLink() );
977 if ( pChain->GetPrev() )
979 SwFlyFrame *pMaster = FindChainNeighbour( *pChain->GetPrev() );
980 if ( GetPrevLink() && pMaster != GetPrevLink() )
981 SwFlyFrame::UnchainFrames( GetPrevLink(), this );
982 if ( pMaster )
984 if ( pMaster->GetNextLink() &&
985 pMaster->GetNextLink() != this )
986 SwFlyFrame::UnchainFrames( pMaster,
987 pMaster->GetNextLink() );
988 if ( !GetPrevLink() )
989 SwFlyFrame::ChainFrames( pMaster, this );
992 else if ( GetPrevLink() )
993 SwFlyFrame::UnchainFrames( GetPrevLink(), this );
995 SAL_FALLTHROUGH;
996 default:
997 bClear = false;
999 if ( bClear )
1001 if ( pOldSet || pNewSet )
1003 if ( pOldSet )
1004 pOldSet->ClearItem( nWhich );
1005 if ( pNewSet )
1006 pNewSet->ClearItem( nWhich );
1008 else
1009 SwLayoutFrame::Modify( pOld, pNew );
1013 /// Gets information from the Modify
1014 bool SwFlyFrame::GetInfo( SfxPoolItem & rInfo ) const
1016 if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
1017 return false; // There's a FlyFrame, so use it
1018 return true; // Continue searching
1021 void SwFlyFrame::Invalidate_( SwPageFrame const *pPage )
1023 InvalidatePage( pPage );
1024 m_bNotifyBack = m_bInvalid = true;
1026 SwFlyFrame *pFrame;
1027 if ( GetAnchorFrame() && nullptr != (pFrame = AnchorFrame()->FindFlyFrame()) )
1029 // Very bad case: If the Fly is bound within another Fly which
1030 // contains columns, the Format should be from that one.
1031 if ( !pFrame->IsLocked() && !pFrame->IsColLocked() &&
1032 pFrame->Lower() && pFrame->Lower()->IsColumnFrame() )
1033 pFrame->InvalidateSize();
1036 // #i85216#
1037 // if vertical position is oriented at a layout frame inside a ghost section,
1038 // assure that the position is invalidated and that the information about
1039 // the vertical position oriented frame is cleared
1040 if ( GetVertPosOrientFrame() && GetVertPosOrientFrame()->IsLayoutFrame() )
1042 const SwSectionFrame* pSectFrame( GetVertPosOrientFrame()->FindSctFrame() );
1043 if ( pSectFrame && pSectFrame->GetSection() == nullptr )
1045 InvalidatePos();
1046 ClearVertPosOrientFrame();
1051 /** Change the relative position
1053 * The position will be Fix automatically and the attribute is changed accordingly.
1055 void SwFlyFrame::ChgRelPos( const Point &rNewPos )
1057 if ( GetCurrRelPos() == rNewPos )
1058 return;
1060 SwFrameFormat *pFormat = GetFormat();
1061 const bool bVert = GetAnchorFrame()->IsVertical();
1062 const SwTwips nNewY = bVert ? rNewPos.X() : rNewPos.Y();
1063 SwTwips nTmpY = nNewY == LONG_MAX ? 0 : nNewY;
1064 if( bVert )
1065 nTmpY = -nTmpY;
1066 SfxItemSet aSet( pFormat->GetDoc()->GetAttrPool(),
1067 svl::Items<RES_VERT_ORIENT, RES_HORI_ORIENT>{});
1069 SwFormatVertOrient aVert( pFormat->GetVertOrient() );
1070 const SwTextFrame *pAutoFrame = nullptr;
1071 // #i34948# - handle also at-page and at-fly anchored
1072 // Writer fly frames
1073 const RndStdIds eAnchorType = GetFrameFormat().GetAnchor().GetAnchorId();
1074 if ( eAnchorType == RndStdIds::FLY_AT_PAGE )
1076 aVert.SetVertOrient( text::VertOrientation::NONE );
1077 aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
1079 else if ( eAnchorType == RndStdIds::FLY_AT_FLY )
1081 aVert.SetVertOrient( text::VertOrientation::NONE );
1082 aVert.SetRelationOrient( text::RelOrientation::FRAME );
1084 else if ( IsFlyAtContentFrame() || text::VertOrientation::NONE != aVert.GetVertOrient() )
1086 if( text::RelOrientation::CHAR == aVert.GetRelationOrient() && IsAutoPos() )
1088 if( LONG_MAX != nNewY )
1090 aVert.SetVertOrient( text::VertOrientation::NONE );
1091 assert(GetAnchorFrame()->IsTextFrame());
1092 pAutoFrame = static_cast<const SwTextFrame*>(GetAnchorFrame());
1093 TextFrameIndex const nOfs(pAutoFrame->MapModelToViewPos(
1094 *pFormat->GetAnchor().GetContentAnchor()));
1095 while( pAutoFrame->GetFollow() &&
1096 pAutoFrame->GetFollow()->GetOfst() <= nOfs )
1098 if( pAutoFrame == GetAnchorFrame() )
1099 nTmpY += pAutoFrame->GetRelPos().Y();
1100 nTmpY -= pAutoFrame->GetUpper()->getFramePrintArea().Height();
1101 pAutoFrame = pAutoFrame->GetFollow();
1103 nTmpY = static_cast<SwFlyAtContentFrame*>(this)->GetRelCharY(pAutoFrame)-nTmpY;
1105 else
1106 aVert.SetVertOrient( text::VertOrientation::CHAR_BOTTOM );
1108 else
1110 aVert.SetVertOrient( text::VertOrientation::NONE );
1111 aVert.SetRelationOrient( text::RelOrientation::FRAME );
1114 aVert.SetPos( nTmpY );
1115 aSet.Put( aVert );
1117 // For Flys in the Cnt, the horizontal orientation is of no interest,
1118 // as it's always 0
1119 if ( !IsFlyInContentFrame() )
1121 const SwTwips nNewX = bVert ? rNewPos.Y() : rNewPos.X();
1122 SwTwips nTmpX = nNewX == LONG_MAX ? 0 : nNewX;
1123 SwFormatHoriOrient aHori( pFormat->GetHoriOrient() );
1124 // #i34948# - handle also at-page and at-fly anchored
1125 // Writer fly frames
1126 if ( eAnchorType == RndStdIds::FLY_AT_PAGE )
1128 aHori.SetHoriOrient( text::HoriOrientation::NONE );
1129 aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
1130 aHori.SetPosToggle( false );
1132 else if ( eAnchorType == RndStdIds::FLY_AT_FLY )
1134 aHori.SetHoriOrient( text::HoriOrientation::NONE );
1135 aHori.SetRelationOrient( text::RelOrientation::FRAME );
1136 aHori.SetPosToggle( false );
1138 else if ( IsFlyAtContentFrame() || text::HoriOrientation::NONE != aHori.GetHoriOrient() )
1140 aHori.SetHoriOrient( text::HoriOrientation::NONE );
1141 if( text::RelOrientation::CHAR == aHori.GetRelationOrient() && IsAutoPos() )
1143 if( LONG_MAX != nNewX )
1145 if( !pAutoFrame )
1147 assert(GetAnchorFrame()->IsTextFrame());
1148 pAutoFrame = static_cast<const SwTextFrame*>(GetAnchorFrame());
1149 TextFrameIndex const nOfs(pAutoFrame->MapModelToViewPos(
1150 *pFormat->GetAnchor().GetContentAnchor()));
1151 while( pAutoFrame->GetFollow() &&
1152 pAutoFrame->GetFollow()->GetOfst() <= nOfs )
1153 pAutoFrame = pAutoFrame->GetFollow();
1155 nTmpX -= static_cast<SwFlyAtContentFrame*>(this)->GetRelCharX(pAutoFrame);
1158 else
1159 aHori.SetRelationOrient( text::RelOrientation::FRAME );
1160 aHori.SetPosToggle( false );
1162 aHori.SetPos( nTmpX );
1163 aSet.Put( aHori );
1165 SetCurrRelPos( rNewPos );
1166 pFormat->GetDoc()->SetAttr( aSet, *pFormat );
1170 /** "Formats" the Frame; Frame and PrtArea.
1172 * The FixSize is not inserted here.
1174 void SwFlyFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderAttrs *pAttrs )
1176 OSL_ENSURE( pAttrs, "FlyFrame::Format, pAttrs is 0." );
1178 ColLock();
1180 if ( !isFrameAreaSizeValid() )
1182 if ( getFrameArea().Top() == FAR_AWAY && getFrameArea().Left() == FAR_AWAY )
1184 // Remove safety switch (see SwFrame::CTor)
1186 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1187 aFrm.Pos().setX(0);
1188 aFrm.Pos().setY(0);
1191 // #i68520#
1192 InvalidateObjRectWithSpaces();
1195 // Check column width and set it if needed
1196 if ( Lower() && Lower()->IsColumnFrame() )
1197 AdjustColumns( nullptr, false );
1199 setFrameAreaSizeValid(true);
1201 const SwTwips nUL = pAttrs->CalcTopLine() + pAttrs->CalcBottomLine();
1202 const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine();
1203 const SwFormatFrameSize &rFrameSz = GetFormat()->GetFrameSize();
1204 Size aRelSize( CalcRel( rFrameSz ) );
1206 OSL_ENSURE( pAttrs->GetSize().Height() != 0 || rFrameSz.GetHeightPercent(), "FrameAttr height is 0." );
1207 OSL_ENSURE( pAttrs->GetSize().Width() != 0 || rFrameSz.GetWidthPercent(), "FrameAttr width is 0." );
1209 SwRectFnSet aRectFnSet(this);
1210 if( !HasFixSize() )
1212 long nMinHeight = 0;
1213 if( IsMinHeight() )
1214 nMinHeight = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
1216 SwTwips nRemaining = CalcContentHeight(pAttrs, nMinHeight, nUL);
1217 if( IsMinHeight() && (nRemaining + nUL) < nMinHeight )
1218 nRemaining = nMinHeight - nUL;
1219 // Because the Grow/Shrink of the Flys does not directly
1220 // set the size - only indirectly by triggering a Format()
1221 // via Invalidate() - the sizes need to be set here.
1222 // Notification is running along already.
1223 // As we already got a lot of zeros per attribute, we block them
1224 // from now on.
1226 if ( nRemaining < MINFLY )
1227 nRemaining = MINFLY;
1230 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1231 aRectFnSet.SetHeight( aPrt, nRemaining );
1234 nRemaining -= aRectFnSet.GetHeight(getFrameArea());
1237 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1238 aRectFnSet.AddBottom( aFrm, nRemaining + nUL );
1241 // #i68520#
1242 if ( nRemaining + nUL != 0 )
1244 InvalidateObjRectWithSpaces();
1247 setFrameAreaSizeValid(true);
1249 if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT))
1251 // This fly is a textbox of a draw shape.
1252 SdrObject* pShape = pShapeFormat->FindSdrObject();
1253 if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pShape) )
1255 // The shape is a customshape: then inform it about the calculated fly size.
1256 Size aSize(aRectFnSet.GetWidth(getFrameArea()), aRectFnSet.GetHeight(getFrameArea()));
1257 pCustomShape->SuggestTextFrameSize(aSize);
1258 // Do the calculations normally done after touching editeng text of the shape.
1259 pCustomShape->NbcSetOutlinerParaObjectForText(nullptr, nullptr);
1263 else
1265 // Fixed Frames do not Format itself
1266 setFrameAreaSizeValid(true);
1268 // Flys set their size using the attr
1269 SwTwips nNewSize = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
1270 nNewSize -= nUL;
1271 if( nNewSize < MINFLY )
1272 nNewSize = MINFLY;
1275 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1276 aRectFnSet.SetHeight( aPrt, nNewSize );
1279 nNewSize += nUL - aRectFnSet.GetHeight(getFrameArea());
1282 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1283 aRectFnSet.AddBottom( aFrm, nNewSize );
1286 // #i68520#
1287 if ( nNewSize != 0 )
1289 InvalidateObjRectWithSpaces();
1293 if ( !m_bFormatHeightOnly )
1295 OSL_ENSURE( aRelSize == CalcRel( rFrameSz ), "SwFlyFrame::Format CalcRel problem" );
1296 SwTwips nNewSize = aRectFnSet.IsVert() ? aRelSize.Height() : aRelSize.Width();
1298 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1300 // #i9046# Autowidth for fly frames
1301 const SwTwips nAutoWidth = lcl_CalcAutoWidth( *this );
1302 if ( nAutoWidth )
1304 if( ATT_MIN_SIZE == rFrameSz.GetWidthSizeType() )
1305 nNewSize = std::max( nNewSize - nLR, nAutoWidth );
1306 else
1307 nNewSize = nAutoWidth;
1310 else
1311 nNewSize -= nLR;
1313 if( nNewSize < MINFLY )
1314 nNewSize = MINFLY;
1317 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1318 aRectFnSet.SetWidth( aPrt, nNewSize );
1321 nNewSize += nLR - aRectFnSet.GetWidth(getFrameArea());
1324 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1325 aRectFnSet.AddRight( aFrm, nNewSize );
1328 // #i68520#
1329 if ( nNewSize != 0 )
1331 InvalidateObjRectWithSpaces();
1335 ColUnlock();
1338 // OD 14.03.2003 #i11760# - change parameter <bNoColl>: type <bool>;
1339 // default value = false.
1340 // OD 14.03.2003 #i11760# - add new parameter <bNoCalcFollow> with
1341 // default value = false.
1342 // OD 11.04.2003 #108824# - new parameter <bNoCalcFollow> was used by method
1343 // <FormatWidthCols(..)> to avoid follow formatting
1344 // for text frames. But, unformatted follows causes
1345 // problems in method <SwContentFrame::WouldFit_(..)>,
1346 // which assumes that the follows are formatted.
1347 // Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
1348 void CalcContent( SwLayoutFrame *pLay, bool bNoColl )
1350 vcl::RenderContext* pRenderContext = pLay->getRootFrame()->GetCurrShell()->GetOut();
1351 SwSectionFrame* pSect;
1352 bool bCollect = false;
1353 if( pLay->IsSctFrame() )
1355 pSect = static_cast<SwSectionFrame*>(pLay);
1356 if( pSect->IsEndnAtEnd() && !bNoColl )
1358 bCollect = true;
1359 SwLayouter::CollectEndnotes( pLay->GetFormat()->GetDoc(), pSect );
1361 pSect->CalcFootnoteContent();
1363 else
1364 pSect = nullptr;
1365 SwFrame *pFrame = pLay->ContainsAny();
1366 if ( !pFrame )
1368 if( pSect )
1370 if( pSect->HasFollow() )
1371 pFrame = pSect->GetFollow()->ContainsAny();
1372 if( !pFrame )
1374 if( pSect->IsEndnAtEnd() )
1376 if( bCollect )
1377 pLay->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->
1378 InsertEndnotes( pSect );
1379 bool bLock = pSect->IsFootnoteLock();
1380 pSect->SetFootnoteLock( true );
1381 pSect->CalcFootnoteContent();
1382 pSect->CalcFootnoteContent();
1383 pSect->SetFootnoteLock( bLock );
1385 return;
1387 pFrame->InvalidatePos_();
1389 else
1390 return;
1392 pFrame->InvalidatePage();
1396 // local variables to avoid loops caused by anchored object positioning
1397 SwAnchoredObject* pAgainObj1 = nullptr;
1398 SwAnchoredObject* pAgainObj2 = nullptr;
1400 // FME 2007-08-30 #i81146# new loop control
1401 int nLoopControlRuns = 0;
1402 const int nLoopControlMax = 20;
1403 const SwFrame* pLoopControlCond = nullptr;
1405 SwFrame* pLast;
1408 pLast = pFrame;
1409 if( pFrame->IsVertical() ?
1410 ( pFrame->GetUpper()->getFramePrintArea().Height() != pFrame->getFrameArea().Height() )
1411 : ( pFrame->GetUpper()->getFramePrintArea().Width() != pFrame->getFrameArea().Width() ) )
1413 pFrame->Prepare( PREP_FIXSIZE_CHG );
1414 pFrame->InvalidateSize_();
1417 if ( pFrame->IsTabFrame() )
1419 static_cast<SwTabFrame*>(pFrame)->m_bCalcLowers = true;
1420 // OD 26.08.2003 #i18103# - lock move backward of follow table,
1421 // if no section content is formatted or follow table belongs
1422 // to the section, which content is formatted.
1423 if ( static_cast<SwTabFrame*>(pFrame)->IsFollow() &&
1424 ( !pSect || pSect == pFrame->FindSctFrame() ) )
1426 static_cast<SwTabFrame*>(pFrame)->m_bLockBackMove = true;
1431 SwFrameDeleteGuard aDeletePageGuard(pSect ? pSect->FindPageFrame() : nullptr);
1432 SwFrameDeleteGuard aDeleteGuard(pSect);
1433 pFrame->Calc(pRenderContext);
1436 // OD 14.03.2003 #i11760# - reset control flag for follow format.
1437 if ( pFrame->IsTextFrame() )
1439 static_cast<SwTextFrame*>(pFrame)->AllowFollowFormat();
1442 // #111937# The keep-attribute can cause the position
1443 // of the prev to be invalid:
1444 // OD 2004-03-15 #116560# - Do not consider invalid previous frame
1445 // due to its keep-attribute, if current frame is a follow or is locked.
1446 // #i44049# - do not consider invalid previous
1447 // frame due to its keep-attribute, if it can't move forward.
1448 // #i57765# - do not consider invalid previous
1449 // frame, if current frame has a column/page break before attribute.
1450 SwFrame* pTmpPrev = pFrame->FindPrev();
1451 SwFlowFrame* pTmpPrevFlowFrame = pTmpPrev && pTmpPrev->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev) : nullptr;
1452 SwFlowFrame* pTmpFlowFrame = pFrame->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pFrame) : nullptr;
1454 bool bPrevInvalid = pTmpPrevFlowFrame && pTmpFlowFrame &&
1455 !pTmpFlowFrame->IsFollow() &&
1456 !StackHack::IsLocked() && // #i76382#
1457 !pTmpFlowFrame->IsJoinLocked() &&
1458 !pTmpPrev->isFrameAreaPositionValid() &&
1459 pLay->IsAnLower( pTmpPrev ) &&
1460 pTmpPrevFlowFrame->IsKeep(pTmpPrev->GetAttrSet()->GetKeep(), pTmpPrev->GetBreakItem()) &&
1461 pTmpPrevFlowFrame->IsKeepFwdMoveAllowed();
1463 // format floating screen objects anchored to the frame.
1464 if ( !bPrevInvalid && pFrame->GetDrawObjs() && pLay->IsAnLower( pFrame ) )
1466 bool bAgain = false;
1467 bool bRestartLayoutProcess = false;
1468 SwPageFrame* pPageFrame = pFrame->FindPageFrame();
1469 size_t nCnt = pFrame->GetDrawObjs()->size();
1470 size_t i = 0;
1471 while ( i < nCnt )
1473 // #i28701#
1474 SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[i];
1476 // determine if anchored object has to be
1477 // formatted and, in case, format it
1478 if ( !pAnchoredObj->PositionLocked() && pAnchoredObj->IsFormatPossible() )
1480 // #i43737# - no invalidation of
1481 // anchored object needed - causes loops for as-character
1482 // anchored objects.
1483 //pAnchoredObj->InvalidateObjPos();
1484 SwRect aRect( pAnchoredObj->GetObjRect() );
1485 if ( !SwObjectFormatter::FormatObj( *pAnchoredObj, pFrame, pPageFrame ) )
1487 bRestartLayoutProcess = true;
1488 break;
1490 // #i3317# - restart layout process,
1491 // if the position of the anchored object is locked now.
1492 if ( pAnchoredObj->PositionLocked() )
1494 bRestartLayoutProcess = true;
1495 break;
1498 if ( aRect != pAnchoredObj->GetObjRect() )
1500 bAgain = true;
1501 if ( pAgainObj2 == pAnchoredObj )
1503 OSL_FAIL( "::CalcContent(..) - loop detected, perform attribute changes to avoid the loop" );
1504 // Prevent oscillation
1505 SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
1506 SwFormatSurround aAttr( rFormat.GetSurround() );
1507 if( css::text::WrapTextMode_THROUGH != aAttr.GetSurround() )
1509 // When on auto position, we can only set it to
1510 // flow through
1511 if ((rFormat.GetAnchor().GetAnchorId() ==
1512 RndStdIds::FLY_AT_CHAR) &&
1513 (css::text::WrapTextMode_PARALLEL ==
1514 aAttr.GetSurround()))
1516 aAttr.SetSurround( css::text::WrapTextMode_THROUGH );
1518 else
1520 aAttr.SetSurround( css::text::WrapTextMode_PARALLEL );
1522 rFormat.LockModify();
1523 rFormat.SetFormatAttr( aAttr );
1524 rFormat.UnlockModify();
1527 else
1529 if ( pAgainObj1 == pAnchoredObj )
1530 pAgainObj2 = pAnchoredObj;
1531 pAgainObj1 = pAnchoredObj;
1535 if ( !pFrame->GetDrawObjs() )
1536 break;
1537 if ( pFrame->GetDrawObjs()->size() < nCnt )
1539 --nCnt;
1540 // Do not increment index, in this case
1541 continue;
1544 ++i;
1547 // #i28701# - restart layout process, if
1548 // requested by floating screen object formatting
1549 if ( bRestartLayoutProcess )
1551 pFrame = pLay->ContainsAny();
1552 pAgainObj1 = nullptr;
1553 pAgainObj2 = nullptr;
1554 continue;
1557 // OD 2004-05-17 #i28701# - format anchor frame after its objects
1558 // are formatted, if the wrapping style influence has to be considered.
1559 if ( pLay->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) )
1561 pFrame->Calc(pRenderContext);
1564 if ( bAgain )
1566 pFrame = pLay->ContainsContent();
1567 if ( pFrame && pFrame->IsInTab() )
1568 pFrame = pFrame->FindTabFrame();
1569 if( pFrame && pFrame->IsInSct() )
1571 SwSectionFrame* pTmp = pFrame->FindSctFrame();
1572 if( pTmp != pLay && pLay->IsAnLower( pTmp ) )
1573 pFrame = pTmp;
1576 if ( pFrame == pLoopControlCond )
1577 ++nLoopControlRuns;
1578 else
1580 nLoopControlRuns = 0;
1581 pLoopControlCond = pFrame;
1584 if ( nLoopControlRuns < nLoopControlMax )
1585 continue;
1587 OSL_FAIL( "LoopControl in CalcContent" );
1590 if ( pFrame->IsTabFrame() )
1592 if ( static_cast<SwTabFrame*>(pFrame)->IsFollow() )
1593 static_cast<SwTabFrame*>(pFrame)->m_bLockBackMove = false;
1596 pFrame = bPrevInvalid ? pTmpPrev : pFrame->FindNext();
1597 if( !bPrevInvalid && pFrame && pFrame->IsSctFrame() && pSect )
1599 // Empty SectionFrames could be present here
1600 while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() )
1601 pFrame = pFrame->FindNext();
1603 // If FindNext returns the Follow of the original Area, we want to
1604 // continue with this content as long as it flows back.
1605 if( pFrame && pFrame->IsSctFrame() && ( pFrame == pSect->GetFollow() ||
1606 static_cast<SwSectionFrame*>(pFrame)->IsAnFollow( pSect ) ) )
1608 pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1609 if( pFrame )
1610 pFrame->InvalidatePos_();
1613 // Stay in the pLay
1614 // Except for SectionFrames with Follow: the first ContentFrame of the Follow
1615 // will be formatted, so that it gets a chance to load in the pLay.
1616 // As long as these Frames are loading in pLay, we continue
1617 } while ( pFrame &&
1618 ( pLay->IsAnLower( pFrame ) ||
1619 ( pSect &&
1620 ( ( pSect->HasFollow() &&
1621 ( pLay->IsAnLower( pLast ) ||
1622 ( pLast->IsInSct() &&
1623 pLast->FindSctFrame()->IsAnFollow(pSect) ) ) &&
1624 pSect->GetFollow()->IsAnLower( pFrame ) ) ||
1625 ( pFrame->IsInSct() &&
1626 pFrame->FindSctFrame()->IsAnFollow( pSect ) ) ) ) ) );
1627 if( pSect )
1629 if( bCollect )
1631 pLay->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->InsertEndnotes(pSect);
1632 pSect->CalcFootnoteContent();
1634 if( pSect->HasFollow() )
1636 SwSectionFrame* pNxt = pSect->GetFollow();
1637 while( pNxt && !pNxt->ContainsContent() )
1638 pNxt = pNxt->GetFollow();
1639 if( pNxt )
1640 pNxt->CalcFootnoteContent();
1642 if( bCollect )
1644 pFrame = pLay->ContainsAny();
1645 bCollect = false;
1646 if( pFrame )
1647 continue;
1650 break;
1652 while( true );
1655 // OD 2004-03-23 #i26791#
1656 void SwFlyFrame::MakeObjPos()
1658 if ( !isFrameAreaPositionValid() )
1660 vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
1661 setFrameAreaPositionValid(true);
1663 // OD 29.10.2003 #113049# - use new class to position object
1664 GetAnchorFrame()->Calc(pRenderContext);
1665 objectpositioning::SwToLayoutAnchoredObjectPosition
1666 aObjPositioning( *GetVirtDrawObj() );
1667 aObjPositioning.CalcPosition();
1669 // #i58280#
1670 // update relative position
1671 SetCurrRelPos( aObjPositioning.GetRelPos() );
1674 SwRectFnSet aRectFnSet(GetAnchorFrame());
1675 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1676 aFrm.Pos( aObjPositioning.GetRelPos() );
1677 aFrm.Pos() += aRectFnSet.GetPos(GetAnchorFrame()->getFrameArea());
1680 // #i69335#
1681 InvalidateObjRectWithSpaces();
1685 void SwFlyFrame::MakePrtArea( const SwBorderAttrs &rAttrs )
1687 if ( !isFramePrintAreaValid() )
1689 setFramePrintAreaValid(true);
1691 // OD 31.07.2003 #110978# - consider vertical layout
1692 SwRectFnSet aRectFnSet(this);
1693 aRectFnSet.SetXMargins( *this, rAttrs.CalcLeftLine(),
1694 rAttrs.CalcRightLine() );
1695 aRectFnSet.SetYMargins( *this, rAttrs.CalcTopLine(),
1696 rAttrs.CalcBottomLine() );
1700 void SwFlyFrame::MakeContentPos( const SwBorderAttrs &rAttrs )
1702 if ( m_bValidContentPos )
1703 return;
1705 m_bValidContentPos = true;
1707 const SwTwips nUL = rAttrs.CalcTopLine() + rAttrs.CalcBottomLine();
1708 Size aRelSize( CalcRel( GetFormat()->GetFrameSize() ) );
1710 SwRectFnSet aRectFnSet(this);
1711 long nMinHeight = 0;
1712 if( IsMinHeight() )
1713 nMinHeight = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
1715 Point aNewContentPos;
1716 aNewContentPos = getFramePrintArea().Pos();
1717 const SdrTextVertAdjust nAdjust = GetFormat()->GetTextVertAdjust().GetValue();
1719 if( nAdjust != SDRTEXTVERTADJUST_TOP )
1721 const SwTwips nContentHeight = CalcContentHeight(&rAttrs, nMinHeight, nUL);
1722 SwTwips nDiff = 0;
1724 if( nContentHeight != 0)
1725 nDiff = aRectFnSet.GetHeight(getFramePrintArea()) - nContentHeight;
1727 if( nDiff > 0 )
1729 if( nAdjust == SDRTEXTVERTADJUST_CENTER )
1731 if( aRectFnSet.IsVertL2R() )
1732 aNewContentPos.setX(aNewContentPos.getX() + nDiff/2);
1733 else if( aRectFnSet.IsVert() )
1734 aNewContentPos.setX(aNewContentPos.getX() - nDiff/2);
1735 else
1736 aNewContentPos.setY(aNewContentPos.getY() + nDiff/2);
1738 else if( nAdjust == SDRTEXTVERTADJUST_BOTTOM )
1740 if( aRectFnSet.IsVertL2R() )
1741 aNewContentPos.setX(aNewContentPos.getX() + nDiff);
1742 else if( aRectFnSet.IsVert() )
1743 aNewContentPos.setX(aNewContentPos.getX() - nDiff);
1744 else
1745 aNewContentPos.setY(aNewContentPos.getY() + nDiff);
1749 if( aNewContentPos != ContentPos() )
1751 ContentPos() = aNewContentPos;
1752 for( SwFrame *pFrame = Lower(); pFrame; pFrame = pFrame->GetNext())
1754 pFrame->InvalidatePos();
1760 void SwFlyFrame::InvalidateContentPos()
1762 m_bValidContentPos = false;
1763 Invalidate_();
1766 SwTwips SwFlyFrame::Grow_( SwTwips nDist, bool bTst )
1768 SwRectFnSet aRectFnSet(this);
1769 if ( Lower() && !IsColLocked() && !HasFixSize() )
1771 SwTwips nSize = aRectFnSet.GetHeight(getFrameArea());
1772 if( nSize > 0 && nDist > ( LONG_MAX - nSize ) )
1773 nDist = LONG_MAX - nSize;
1775 if ( nDist <= 0 )
1776 return 0;
1778 if ( Lower()->IsColumnFrame() )
1779 { // If it's a Column Frame, the Format takes control of the
1780 // resizing (due to the adjustment).
1781 if ( !bTst )
1783 // #i28701# - unlock position of Writer fly frame
1784 UnlockPosition();
1785 InvalidatePos_();
1786 InvalidateSize();
1788 return 0;
1791 if ( !bTst )
1793 const SwRect aOld( GetObjRectWithSpaces() );
1794 InvalidateSize_();
1795 const bool bOldLock = m_bLocked;
1796 Unlock();
1797 if ( IsFlyFreeFrame() )
1799 // #i37068# - no format of position here
1800 // and prevent move in method <CheckClip(..)>.
1801 // This is needed to prevent layout loop caused by nested
1802 // Writer fly frames - inner Writer fly frames format its
1803 // anchor, which grows/shrinks the outer Writer fly frame.
1804 // Note: position will be invalidated below.
1805 setFrameAreaPositionValid(true);
1807 // #i55416#
1808 // Suppress format of width for autowidth frame, because the
1809 // format of the width would call <SwTextFrame::CalcFitToContent()>
1810 // for the lower frame, which initiated this grow.
1811 const bool bOldFormatHeightOnly = m_bFormatHeightOnly;
1812 const SwFormatFrameSize& rFrameSz = GetFormat()->GetFrameSize();
1813 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1815 m_bFormatHeightOnly = true;
1817 SwViewShell* pSh = getRootFrame()->GetCurrShell();
1818 if (pSh)
1820 static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( true );
1821 static_cast<SwFlyFreeFrame*>(this)->SwFlyFreeFrame::MakeAll(pSh->GetOut());
1822 static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( false );
1824 // #i55416#
1825 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1827 m_bFormatHeightOnly = bOldFormatHeightOnly;
1830 else
1831 MakeAll(getRootFrame()->GetCurrShell()->GetOut());
1832 InvalidateSize_();
1833 InvalidatePos();
1834 if ( bOldLock )
1835 Lock();
1836 const SwRect aNew( GetObjRectWithSpaces() );
1837 if ( aOld != aNew )
1838 ::Notify( this, FindPageFrame(), aOld );
1839 return aRectFnSet.GetHeight(aNew)-aRectFnSet.GetHeight(aOld);
1841 return nDist;
1843 return 0;
1846 SwTwips SwFlyFrame::Shrink_( SwTwips nDist, bool bTst )
1848 if( Lower() && !IsColLocked() && !HasFixSize() )
1850 SwRectFnSet aRectFnSet(this);
1851 SwTwips nHeight = aRectFnSet.GetHeight(getFrameArea());
1852 if ( nDist > nHeight )
1853 nDist = nHeight;
1855 SwTwips nVal = nDist;
1856 if ( IsMinHeight() )
1858 const SwFormatFrameSize& rFormatSize = GetFormat()->GetFrameSize();
1859 SwTwips nFormatHeight = aRectFnSet.IsVert() ? rFormatSize.GetWidth() : rFormatSize.GetHeight();
1861 nVal = std::min( nDist, nHeight - nFormatHeight );
1864 if ( nVal <= 0 )
1865 return 0;
1867 if ( Lower()->IsColumnFrame() )
1868 { // If it's a Column Frame, the Format takes control of the
1869 // resizing (due to the adjustment).
1870 if ( !bTst )
1872 SwRect aOld( GetObjRectWithSpaces() );
1875 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1876 aRectFnSet.SetHeight( aFrm, nHeight - nVal );
1879 // #i68520#
1880 if ( nHeight - nVal != 0 )
1882 InvalidateObjRectWithSpaces();
1885 nHeight = aRectFnSet.GetHeight(getFramePrintArea());
1888 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1889 aRectFnSet.SetHeight( aPrt, nHeight - nVal );
1892 InvalidatePos_();
1893 InvalidateSize();
1894 ::Notify( this, FindPageFrame(), aOld );
1895 NotifyDrawObj();
1896 if ( GetAnchorFrame()->IsInFly() )
1897 AnchorFrame()->FindFlyFrame()->Shrink( nDist, bTst );
1899 return 0;
1902 if ( !bTst )
1904 const SwRect aOld( GetObjRectWithSpaces() );
1905 InvalidateSize_();
1906 const bool bOldLocked = m_bLocked;
1907 Unlock();
1908 if ( IsFlyFreeFrame() )
1910 // #i37068# - no format of position here
1911 // and prevent move in method <CheckClip(..)>.
1912 // This is needed to prevent layout loop caused by nested
1913 // Writer fly frames - inner Writer fly frames format its
1914 // anchor, which grows/shrinks the outer Writer fly frame.
1915 // Note: position will be invalidated below.
1916 setFrameAreaPositionValid(true);
1918 // #i55416#
1919 // Suppress format of width for autowidth frame, because the
1920 // format of the width would call <SwTextFrame::CalcFitToContent()>
1921 // for the lower frame, which initiated this shrink.
1922 const bool bOldFormatHeightOnly = m_bFormatHeightOnly;
1923 const SwFormatFrameSize& rFrameSz = GetFormat()->GetFrameSize();
1924 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1926 m_bFormatHeightOnly = true;
1928 static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( true );
1929 static_cast<SwFlyFreeFrame*>(this)->SwFlyFreeFrame::MakeAll(getRootFrame()->GetCurrShell()->GetOut());
1930 static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( false );
1931 // #i55416#
1932 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1934 m_bFormatHeightOnly = bOldFormatHeightOnly;
1937 else
1938 MakeAll(getRootFrame()->GetCurrShell()->GetOut());
1939 InvalidateSize_();
1940 InvalidatePos();
1941 if ( bOldLocked )
1942 Lock();
1943 const SwRect aNew( GetObjRectWithSpaces() );
1944 if ( aOld != aNew )
1946 ::Notify( this, FindPageFrame(), aOld );
1947 if ( GetAnchorFrame()->IsInFly() )
1948 AnchorFrame()->FindFlyFrame()->Shrink( nDist, bTst );
1950 return aRectFnSet.GetHeight(aOld) -
1951 aRectFnSet.GetHeight(aNew);
1953 return nVal;
1955 return 0;
1958 Size SwFlyFrame::ChgSize( const Size& aNewSize )
1960 // #i53298#
1961 // If the fly frame anchored at-paragraph or at-character contains an OLE
1962 // object, assure that the new size fits into the current clipping area
1963 // of the fly frame
1964 Size aAdjustedNewSize( aNewSize );
1966 if ( dynamic_cast<SwFlyAtContentFrame*>(this) &&
1967 Lower() && dynamic_cast<SwNoTextFrame*>(Lower()) &&
1968 static_cast<SwNoTextFrame*>(Lower())->GetNode()->GetOLENode() )
1970 SwRect aClipRect;
1971 ::CalcClipRect( GetVirtDrawObj(), aClipRect, false );
1972 if ( aAdjustedNewSize.Width() > aClipRect.Width() )
1974 aAdjustedNewSize.setWidth( aClipRect.Width() );
1976 if ( aAdjustedNewSize.Height() > aClipRect.Height() )
1978 aAdjustedNewSize.setWidth( aClipRect.Height() );
1983 if ( aAdjustedNewSize != getFrameArea().SSize() )
1985 SwFrameFormat *pFormat = GetFormat();
1986 SwFormatFrameSize aSz( pFormat->GetFrameSize() );
1987 aSz.SetWidth( aAdjustedNewSize.Width() );
1988 aSz.SetHeight( aAdjustedNewSize.Height() );
1989 // go via the Doc for UNDO
1990 pFormat->GetDoc()->SetAttr( aSz, *pFormat );
1991 return aSz.GetSize();
1993 else
1994 return getFrameArea().SSize();
1997 bool SwFlyFrame::IsLowerOf( const SwLayoutFrame* pUpperFrame ) const
1999 OSL_ENSURE( GetAnchorFrame(), "8-( Fly is lost in Space." );
2000 const SwFrame* pFrame = GetAnchorFrame();
2003 if ( pFrame == pUpperFrame )
2004 return true;
2005 pFrame = pFrame->IsFlyFrame()
2006 ? static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame()
2007 : pFrame->GetUpper();
2008 } while ( pFrame );
2009 return false;
2012 void SwFlyFrame::Cut()
2016 void SwFrame::AppendFly( SwFlyFrame *pNew )
2018 if (!m_pDrawObjs)
2020 m_pDrawObjs.reset(new SwSortedObjs());
2022 m_pDrawObjs->Insert( *pNew );
2023 pNew->ChgAnchorFrame( this );
2025 // Register at the page
2026 // If there's none present, register via SwPageFrame::PreparePage
2027 SwPageFrame* pPage = FindPageFrame();
2028 if ( pPage != nullptr )
2030 pPage->AppendFlyToPage( pNew );
2034 void SwFrame::RemoveFly( SwFlyFrame *pToRemove )
2036 // Deregister from the page
2037 // Could already have happened, if the page was already destructed
2038 SwPageFrame *pPage = pToRemove->FindPageFrame();
2039 if ( pPage && pPage->GetSortedObjs() )
2041 pPage->RemoveFlyFromPage( pToRemove );
2043 // #i73201#
2044 else
2046 if ( pToRemove->IsAccessibleFrame() &&
2047 pToRemove->GetFormat() &&
2048 !pToRemove->IsFlyInContentFrame() )
2050 SwRootFrame *pRootFrame = getRootFrame();
2051 if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
2053 SwViewShell *pVSh = pRootFrame->GetCurrShell();
2054 if( pVSh && pVSh->Imp() )
2056 pVSh->Imp()->DisposeAccessibleFrame( pToRemove );
2062 m_pDrawObjs->Remove(*pToRemove);
2063 if (!m_pDrawObjs->size())
2065 m_pDrawObjs.reset();
2068 pToRemove->ChgAnchorFrame( nullptr );
2070 if ( !pToRemove->IsFlyInContentFrame() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
2071 GetUpper()->InvalidateSize();
2074 void SwFrame::AppendDrawObj( SwAnchoredObject& _rNewObj )
2076 assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2078 if ( dynamic_cast<const SwAnchoredDrawObject*>( &_rNewObj) == nullptr )
2080 OSL_FAIL( "SwFrame::AppendDrawObj(..) - anchored object of unexpected type -> object not appended" );
2081 return;
2084 if ( dynamic_cast<const SwDrawVirtObj*>(_rNewObj.GetDrawObj()) == nullptr &&
2085 _rNewObj.GetAnchorFrame() && _rNewObj.GetAnchorFrame() != this )
2087 assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2088 // perform disconnect from layout, if 'master' drawing object is appended
2089 // to a new frame.
2090 static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
2091 DisconnectFromLayout( false );
2092 assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2095 if ( _rNewObj.GetAnchorFrame() != this )
2097 if (!m_pDrawObjs)
2099 m_pDrawObjs.reset(new SwSortedObjs());
2101 m_pDrawObjs->Insert(_rNewObj);
2102 _rNewObj.ChgAnchorFrame( this );
2105 // #i113730#
2106 // Assure the control objects and group objects containing controls are on the control layer
2107 if ( ::CheckControlLayer( _rNewObj.DrawObj() ) )
2109 const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
2110 const SdrLayerID aCurrentLayer(_rNewObj.DrawObj()->GetLayer());
2111 const SdrLayerID aControlLayerID(rIDDMA.GetControlsId());
2112 const SdrLayerID aInvisibleControlLayerID(rIDDMA.GetInvisibleControlsId());
2114 if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
2116 if ( aCurrentLayer == rIDDMA.GetInvisibleHellId() ||
2117 aCurrentLayer == rIDDMA.GetInvisibleHeavenId() )
2119 _rNewObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
2121 else
2123 _rNewObj.DrawObj()->SetLayer(aControlLayerID);
2125 //The layer is part of the key used to sort the obj, so update
2126 //its position if the layer changed.
2127 m_pDrawObjs->Update(_rNewObj);
2131 // no direct positioning needed, but invalidate the drawing object position
2132 _rNewObj.InvalidateObjPos();
2134 // register at page frame
2135 SwPageFrame* pPage = FindPageFrame();
2136 if ( pPage )
2138 pPage->AppendDrawObjToPage( _rNewObj );
2141 // Notify accessible layout.
2142 SwViewShell* pSh = getRootFrame()->GetCurrShell();
2143 if( pSh )
2145 SwRootFrame* pLayout = getRootFrame();
2146 if( pLayout && pLayout->IsAnyShellAccessible() )
2148 pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
2152 assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2155 void SwFrame::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
2157 // Notify accessible layout.
2158 SwViewShell* pSh = getRootFrame()->GetCurrShell();
2159 if( pSh )
2161 SwRootFrame* pLayout = getRootFrame();
2162 if (pLayout && pLayout->IsAnyShellAccessible())
2163 pSh->Imp()->DisposeAccessibleObj(_rToRemoveObj.GetDrawObj(), false);
2166 // deregister from page frame
2167 SwPageFrame* pPage = _rToRemoveObj.GetPageFrame();
2168 if ( pPage && pPage->GetSortedObjs() )
2169 pPage->RemoveDrawObjFromPage( _rToRemoveObj );
2171 m_pDrawObjs->Remove(_rToRemoveObj);
2172 if (!m_pDrawObjs->size())
2174 m_pDrawObjs.reset();
2176 _rToRemoveObj.ChgAnchorFrame( nullptr );
2178 assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2181 void SwFrame::InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs )
2183 if ( GetDrawObjs() )
2185 // #i26945# - determine page the frame is on,
2186 // in order to check, if anchored object is registered at the same
2187 // page.
2188 const SwPageFrame* pPageFrame = FindPageFrame();
2189 // #i28701# - re-factoring
2190 for (SwAnchoredObject* pAnchoredObj : *GetDrawObjs())
2192 if ( _bNoInvaOfAsCharAnchoredObjs &&
2193 (pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
2194 == RndStdIds::FLY_AS_CHAR) )
2196 continue;
2198 // #i26945# - no invalidation, if anchored object
2199 // isn't registered at the same page and instead is registered at
2200 // the page, where its anchor character text frame is on.
2201 if ( pAnchoredObj->GetPageFrame() &&
2202 pAnchoredObj->GetPageFrame() != pPageFrame )
2204 SwTextFrame* pAnchorCharFrame = pAnchoredObj->FindAnchorCharFrame();
2205 if ( pAnchorCharFrame &&
2206 pAnchoredObj->GetPageFrame() == pAnchorCharFrame->FindPageFrame() )
2208 continue;
2210 // #115759# - unlock its position, if anchored
2211 // object isn't registered at the page, where its anchor
2212 // character text frame is on, respectively if it has no
2213 // anchor character text frame.
2214 else
2216 pAnchoredObj->UnlockPosition();
2219 // #i51474# - reset flag, that anchored object
2220 // has cleared environment, and unlock its position, if the anchored
2221 // object is registered at the same page as the anchor frame is on.
2222 if ( pAnchoredObj->ClearedEnvironment() &&
2223 pAnchoredObj->GetPageFrame() &&
2224 pAnchoredObj->GetPageFrame() == pPageFrame )
2226 pAnchoredObj->UnlockPosition();
2227 pAnchoredObj->SetClearedEnvironment( false );
2229 // distinguish between writer fly frames and drawing objects
2230 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) != nullptr )
2232 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
2233 pFly->Invalidate_();
2234 pFly->InvalidatePos_();
2236 else
2238 pAnchoredObj->InvalidateObjPos();
2240 } // end of loop on objects, which are connected to the frame
2244 // #i26945# - correct check, if anchored object is a lower
2245 // of the layout frame. E.g., anchor character text frame can be a follow text
2246 // frame.
2247 // #i44016# - add parameter <_bUnlockPosOfObjs> to
2248 // force an unlockposition call for the lower objects.
2249 void SwLayoutFrame::NotifyLowerObjs( const bool _bUnlockPosOfObjs )
2251 // invalidate lower floating screen objects
2252 SwPageFrame* pPageFrame = FindPageFrame();
2253 if ( pPageFrame && pPageFrame->GetSortedObjs() )
2255 SwSortedObjs& rObjs = *(pPageFrame->GetSortedObjs());
2256 for (SwAnchoredObject* pObj : rObjs)
2258 // #i26945# - check, if anchored object is a lower
2259 // of the layout frame is changed to check, if its anchor frame
2260 // is a lower of the layout frame.
2261 // determine the anchor frame - usually it's the anchor frame,
2262 // for at-character/as-character anchored objects the anchor character
2263 // text frame is taken.
2264 const SwFrame* pAnchorFrame = pObj->GetAnchorFrameContainingAnchPos();
2265 if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr )
2267 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObj);
2269 if ( pFly->getFrameArea().Left() == FAR_AWAY )
2270 continue;
2272 if ( pFly->IsAnLower( this ) )
2273 continue;
2275 // #i26945# - use <pAnchorFrame> to check, if
2276 // fly frame is lower of layout frame resp. if fly frame is
2277 // at a different page registered as its anchor frame is on.
2278 const bool bLow = IsAnLower( pAnchorFrame );
2279 if ( bLow || pAnchorFrame->FindPageFrame() != pPageFrame )
2281 pFly->Invalidate_( pPageFrame );
2282 if ( !bLow || pFly->IsFlyAtContentFrame() )
2284 // #i44016#
2285 if ( _bUnlockPosOfObjs )
2287 pFly->UnlockPosition();
2289 pFly->InvalidatePos_();
2291 else
2292 pFly->InvalidatePrt_();
2295 else
2297 OSL_ENSURE( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr,
2298 "<SwLayoutFrame::NotifyFlys() - anchored object of unexpected type" );
2299 // #i26945# - use <pAnchorFrame> to check, if
2300 // fly frame is lower of layout frame resp. if fly frame is
2301 // at a different page registered as its anchor frame is on.
2302 if ( IsAnLower( pAnchorFrame ) ||
2303 pAnchorFrame->FindPageFrame() != pPageFrame )
2305 // #i44016#
2306 if ( _bUnlockPosOfObjs )
2308 pObj->UnlockPosition();
2310 pObj->InvalidateObjPos();
2317 void SwFlyFrame::NotifyDrawObj()
2319 SwVirtFlyDrawObj* pObj = GetVirtDrawObj();
2320 pObj->SetRect();
2321 pObj->SetRectsDirty();
2322 pObj->SetChanged();
2323 pObj->BroadcastObjectChange();
2325 if ( GetFormat()->GetSurround().IsContour() )
2327 ClrContourCache( pObj );
2329 else if(IsFlyFreeFrame() && static_cast< const SwFlyFreeFrame* >(this)->supportsAutoContour())
2331 // RotateFlyFrame3: Also need to clear when changes happen
2332 // Caution: isTransformableSwFrame is already reset when resetting rotation, so
2333 // *additionally* reset in SwFlyFreeFrame::MakeAll when no more rotation
2334 ClrContourCache( pObj );
2338 Size SwFlyFrame::CalcRel( const SwFormatFrameSize &rSz ) const
2340 Size aRet( rSz.GetSize() );
2342 const SwFrame *pRel = IsFlyLayFrame() ? GetAnchorFrame() : GetAnchorFrame()->GetUpper();
2343 if( pRel ) // LAYER_IMPL
2345 long nRelWidth = LONG_MAX, nRelHeight = LONG_MAX;
2346 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
2347 if ( ( pRel->IsBodyFrame() || pRel->IsPageFrame() ) &&
2348 pSh && pSh->GetViewOptions()->getBrowseMode() &&
2349 pSh->VisArea().HasArea() )
2351 nRelWidth = pSh->GetBrowseWidth();
2352 nRelHeight = pSh->VisArea().Height();
2353 Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
2354 nRelWidth = std::min( nRelWidth, pRel->getFramePrintArea().Width() );
2355 nRelHeight -= 2*aBorder.Height();
2356 nRelHeight = std::min( nRelHeight, pRel->getFramePrintArea().Height() );
2359 // At the moment only the "== PAGE_FRAME" and "!= PAGE_FRAME" cases are handled.
2360 // When size is a relative to page size, ignore size of SwBodyFrame.
2361 if (rSz.GetWidthPercentRelation() != text::RelOrientation::PAGE_FRAME)
2362 nRelWidth = std::min( nRelWidth, pRel->getFramePrintArea().Width() );
2363 else if ( pRel->IsPageFrame() )
2364 nRelWidth = std::min( nRelWidth, pRel->getFrameArea().Width() );
2366 if (rSz.GetHeightPercentRelation() != text::RelOrientation::PAGE_FRAME)
2367 nRelHeight = std::min( nRelHeight, pRel->getFramePrintArea().Height() );
2368 else if ( pRel->IsPageFrame() )
2369 nRelHeight = std::min( nRelHeight, pRel->getFrameArea().Height() );
2371 if( !pRel->IsPageFrame() )
2373 const SwPageFrame* pPage = FindPageFrame();
2374 if( pPage )
2376 if (rSz.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME)
2377 // Ignore margins of pPage.
2378 nRelWidth = std::min( nRelWidth, pPage->getFrameArea().Width() );
2379 else
2380 nRelWidth = std::min( nRelWidth, pPage->getFramePrintArea().Width() );
2381 if (rSz.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME)
2382 // Ignore margins of pPage.
2383 nRelHeight = std::min( nRelHeight, pPage->getFrameArea().Height() );
2384 else
2385 nRelHeight = std::min( nRelHeight, pPage->getFramePrintArea().Height() );
2389 if ( rSz.GetWidthPercent() && rSz.GetWidthPercent() != SwFormatFrameSize::SYNCED )
2390 aRet.setWidth( nRelWidth * rSz.GetWidthPercent() / 100 );
2391 if ( rSz.GetHeightPercent() && rSz.GetHeightPercent() != SwFormatFrameSize::SYNCED )
2392 aRet.setHeight( nRelHeight * rSz.GetHeightPercent() / 100 );
2394 if ( rSz.GetWidthPercent() == SwFormatFrameSize::SYNCED )
2396 aRet.setWidth( aRet.Width() * ( aRet.Height()) );
2397 aRet.setWidth( aRet.Width() / ( rSz.GetHeight()) );
2399 else if ( rSz.GetHeightPercent() == SwFormatFrameSize::SYNCED )
2401 aRet.setHeight( aRet.Height() * ( aRet.Width()) );
2402 aRet.setHeight( aRet.Height() / ( rSz.GetWidth()) );
2405 return aRet;
2408 static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame )
2410 SwTwips nRet = 0;
2411 SwTwips nMin = 0;
2412 const SwFrame* pFrame = rFrame.Lower();
2414 // No autowidth defined for columned frames
2415 if ( !pFrame || pFrame->IsColumnFrame() )
2416 return nRet;
2418 while ( pFrame )
2420 if ( pFrame->IsSctFrame() )
2422 nMin = lcl_CalcAutoWidth( *static_cast<const SwSectionFrame*>(pFrame) );
2424 if ( pFrame->IsTextFrame() )
2426 nMin = const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pFrame))->CalcFitToContent();
2427 const SvxLRSpaceItem &rSpace =
2428 static_cast<const SwTextFrame*>(pFrame)->GetTextNodeForParaProps()->GetSwAttrSet().GetLRSpace();
2429 if (!static_cast<const SwTextFrame*>(pFrame)->IsLocked())
2430 nMin += rSpace.GetRight() + rSpace.GetTextLeft() + rSpace.GetTextFirstLineOfst();
2432 else if ( pFrame->IsTabFrame() )
2434 const SwFormatFrameSize& rTableFormatSz = static_cast<const SwTabFrame*>(pFrame)->GetTable()->GetFrameFormat()->GetFrameSize();
2435 if ( USHRT_MAX == rTableFormatSz.GetSize().Width() ||
2436 text::HoriOrientation::NONE == static_cast<const SwTabFrame*>(pFrame)->GetFormat()->GetHoriOrient().GetHoriOrient() )
2438 const SwPageFrame* pPage = rFrame.FindPageFrame();
2439 // auto width table
2440 nMin = pFrame->GetUpper()->IsVertical() ?
2441 pPage->getFramePrintArea().Height() :
2442 pPage->getFramePrintArea().Width();
2444 else
2446 nMin = rTableFormatSz.GetSize().Width();
2450 if ( nMin > nRet )
2451 nRet = nMin;
2453 pFrame = pFrame->GetNext();
2456 return nRet;
2459 /// OD 16.04.2003 #i13147# - If called for paint and the <SwNoTextFrame> contains
2460 /// a graphic, load of intrinsic graphic has to be avoided.
2461 bool SwFlyFrame::GetContour( tools::PolyPolygon& rContour,
2462 const bool _bForPaint ) const
2464 vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
2465 bool bRet = false;
2466 const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame());
2468 if(bIsCandidate)
2470 if(GetFormat()->GetSurround().IsContour())
2472 SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwNoTextFrame*>(Lower())->GetNode()));
2473 // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
2474 // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic
2475 // node and method is called for paint.
2476 std::unique_ptr<GraphicObject> xTmpGrfObj;
2477 const GraphicObject* pGrfObj = nullptr;
2478 const SwGrfNode* pGrfNd = pNd->GetGrfNode();
2479 if ( pGrfNd && _bForPaint )
2481 pGrfObj = &(pGrfNd->GetGrfObj());
2483 else
2485 xTmpGrfObj.reset(new GraphicObject(pNd->GetGraphic()));
2486 pGrfObj = xTmpGrfObj.get();
2488 assert(pGrfObj && "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>.");
2489 if (pGrfObj->GetType() != GraphicType::NONE)
2491 if( !pNd->HasContour() )
2493 // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
2494 // during paint. Thus, return (value of <bRet> should be <false>).
2495 if ( pGrfNd && _bForPaint )
2497 OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." );
2498 return bRet;
2500 pNd->CreateContour();
2502 pNd->GetContour( rContour );
2503 // The Node holds the Polygon matching the original size of the graphic
2504 // We need to include the scaling here
2505 SwRect aClip;
2506 SwRect aOrig;
2507 Lower()->Calc(pRenderContext);
2508 static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig );
2509 // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
2510 // in order to avoid that graphic has to be loaded for contour scale.
2511 //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() );
2513 OutputDevice* pOutDev = Application::GetDefaultDevice();
2514 const MapMode aDispMap( MapUnit::MapTwip );
2515 const MapMode aGrfMap( pGrfObj->GetPrefMapMode() );
2516 const Size aGrfSize( pGrfObj->GetPrefSize() );
2517 Size aOrgSize;
2518 Point aNewPoint;
2519 bool bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;
2521 if ( bPixelMap )
2522 aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
2523 else
2524 aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap );
2526 if ( aOrgSize.Width() && aOrgSize.Height() )
2528 double fScaleX = static_cast<double>(aOrig.Width()) / aOrgSize.Width();
2529 double fScaleY = static_cast<double>(aOrig.Height()) / aOrgSize.Height();
2531 for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
2533 tools::Polygon& rPoly = rContour[ j ];
2535 for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
2537 if ( bPixelMap )
2538 aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap );
2539 else
2540 aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap );
2542 rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) );
2547 // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
2548 xTmpGrfObj.reset();
2549 rContour.Move( aOrig.Left(), aOrig.Top() );
2550 if( !aClip.Width() )
2551 aClip.Width( 1 );
2552 if( !aClip.Height() )
2553 aClip.Height( 1 );
2554 rContour.Clip( aClip.SVRect() );
2555 rContour.Optimize(PolyOptimizeFlags::CLOSE);
2556 bRet = true;
2559 else
2561 const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(this));
2563 if(nullptr != pSwFlyFreeFrame &&
2564 pSwFlyFreeFrame->supportsAutoContour() &&
2565 // isTransformableSwFrame already used in supportsAutoContour(), but
2566 // better check twice when it may get changed there...
2567 pSwFlyFreeFrame->isTransformableSwFrame())
2569 // RotateFlyFrame: use untransformed SwFrame to allow text floating around.
2570 // Will be transformed below
2571 const TransformableSwFrame* pTransformableSwFrame(pSwFlyFreeFrame->getTransformableSwFrame());
2572 const SwRect aFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
2573 rContour = tools::PolyPolygon(tools::Polygon(aFrameArea.SVRect()));
2574 bRet = (0 != rContour.Count());
2578 if(bRet && 0 != rContour.Count())
2580 const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(this));
2582 if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->isTransformableSwFrame())
2584 // Need to adapt contour to transformation
2585 basegfx::B2DVector aScale, aTranslate;
2586 double fRotate, fShearX;
2587 getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
2589 if(!basegfx::fTools::equalZero(fRotate))
2591 basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon());
2592 const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
2593 const basegfx::B2DHomMatrix aRotateAroundCenter(
2594 basegfx::utils::createRotateAroundPoint(
2595 aCenter.getX(),
2596 aCenter.getY(),
2597 fRotate));
2598 aSource.transform(aRotateAroundCenter);
2599 rContour = tools::PolyPolygon(aSource);
2605 return bRet;
2608 // OD 2004-03-25 #i26791#
2609 const SwVirtFlyDrawObj* SwFlyFrame::GetVirtDrawObj() const
2611 return static_cast<const SwVirtFlyDrawObj*>(GetDrawObj());
2613 SwVirtFlyDrawObj* SwFlyFrame::GetVirtDrawObj()
2615 return static_cast<SwVirtFlyDrawObj*>(DrawObj());
2618 // OD 2004-03-24 #i26791# - implementation of pure virtual method declared in
2619 // base class <SwAnchoredObject>
2621 void SwFlyFrame::InvalidateObjPos()
2623 InvalidatePos();
2624 // #i68520#
2625 InvalidateObjRectWithSpaces();
2628 SwFrameFormat& SwFlyFrame::GetFrameFormat()
2630 OSL_ENSURE( GetFormat(),
2631 "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
2632 return *GetFormat();
2634 const SwFrameFormat& SwFlyFrame::GetFrameFormat() const
2636 OSL_ENSURE( GetFormat(),
2637 "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
2638 return *GetFormat();
2641 const SwRect SwFlyFrame::GetObjRect() const
2643 return getFrameArea();
2646 // #i70122#
2647 // for Writer fly frames the bounding rectangle equals the object rectangles
2648 const SwRect SwFlyFrame::GetObjBoundRect() const
2650 return GetObjRect();
2653 // #i68520#
2654 bool SwFlyFrame::SetObjTop_( const SwTwips _nTop )
2656 const bool bChanged( getFrameArea().Pos().getY() != _nTop );
2657 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2658 aFrm.Pos().setY(_nTop);
2660 return bChanged;
2662 bool SwFlyFrame::SetObjLeft_( const SwTwips _nLeft )
2664 const bool bChanged( getFrameArea().Pos().getX() != _nLeft );
2665 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2666 aFrm.Pos().setX(_nLeft);
2668 return bChanged;
2671 /** method to assure that anchored object is registered at the correct
2672 page frame
2674 OD 2004-07-02 #i28701#
2676 void SwFlyFrame::RegisterAtCorrectPage()
2678 // default behaviour is to do nothing.
2681 /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
2683 OD 2004-05-11 #i28701#
2685 bool SwFlyFrame::IsFormatPossible() const
2687 return SwAnchoredObject::IsFormatPossible() &&
2688 !IsLocked() && !IsColLocked();
2691 void SwFlyFrame::GetAnchoredObjects( std::vector<SwAnchoredObject*>& aVector, const SwFormat& rFormat )
2693 SwIterator<SwFlyFrame,SwFormat> aIter( rFormat );
2694 for( SwFlyFrame* pFlyFrame = aIter.First(); pFlyFrame; pFlyFrame = aIter.Next() )
2695 aVector.push_back( pFlyFrame );
2698 const SwFlyFrameFormat * SwFlyFrame::GetFormat() const
2700 return static_cast< const SwFlyFrameFormat * >( GetDep() );
2703 SwFlyFrameFormat * SwFlyFrame::GetFormat()
2705 return static_cast< SwFlyFrameFormat * >( GetDep() );
2708 void SwFlyFrame::Calc(vcl::RenderContext* pRenderContext) const
2710 if ( !m_bValidContentPos )
2711 const_cast<SwFlyFrame*>(this)->PrepareMake(pRenderContext);
2712 else
2713 SwLayoutFrame::Calc(pRenderContext);
2716 SwTwips SwFlyFrame::CalcContentHeight(const SwBorderAttrs *pAttrs, const SwTwips nMinHeight, const SwTwips nUL)
2718 SwRectFnSet aRectFnSet(this);
2719 SwTwips nHeight = 0;
2720 if ( Lower() )
2722 if ( Lower()->IsColumnFrame() )
2724 FormatWidthCols( *pAttrs, nUL, nMinHeight );
2725 nHeight = aRectFnSet.GetHeight(Lower()->getFrameArea());
2727 else
2729 SwFrame *pFrame = Lower();
2730 while ( pFrame )
2732 nHeight += aRectFnSet.GetHeight(pFrame->getFrameArea());
2733 if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
2734 // This TextFrame would like to be a bit larger
2735 nHeight += static_cast<SwTextFrame*>(pFrame)->GetParHeight()
2736 - aRectFnSet.GetHeight(pFrame->getFramePrintArea());
2737 else if( pFrame->IsSctFrame() && static_cast<SwSectionFrame*>(pFrame)->IsUndersized() )
2738 nHeight += static_cast<SwSectionFrame*>(pFrame)->Undersize();
2739 pFrame = pFrame->GetNext();
2742 if ( GetDrawObjs() )
2744 const size_t nCnt = GetDrawObjs()->size();
2745 SwTwips nTop = aRectFnSet.GetTop(getFrameArea());
2746 SwTwips nBorder = aRectFnSet.GetHeight(getFrameArea()) -
2747 aRectFnSet.GetHeight(getFramePrintArea());
2748 for ( size_t i = 0; i < nCnt; ++i )
2750 SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
2751 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) != nullptr )
2753 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
2754 // OD 06.11.2003 #i22305# - consider
2755 // only Writer fly frames, which follow the text flow.
2756 if ( pFly->IsFlyLayFrame() &&
2757 pFly->getFrameArea().Top() != FAR_AWAY &&
2758 pFly->GetFormat()->GetFollowTextFlow().GetValue() )
2760 SwTwips nDist = -aRectFnSet.BottomDist( pFly->getFrameArea(), nTop );
2761 if( nDist > nBorder + nHeight )
2762 nHeight = nDist - nBorder;
2768 return nHeight;
2771 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */