1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <svl/itemiter.hxx>
21 #include <vcl/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 <editeng/outlobj.hxx>
28 #include <drawdoc.hxx>
29 #include <fmtfsize.hxx>
30 #include <fmtclds.hxx>
31 #include <fmtcntnt.hxx>
32 #include <fmturl.hxx>
33 #include <fmtsrnd.hxx>
34 #include <fmtornt.hxx>
35 #include <fmtcnct.hxx>
36 #include <ndgrf.hxx>
37 #include <tolayoutanchoredobjectposition.hxx>
38 #include <fmtfollowtextflow.hxx>
39 #include <sortedobjs.hxx>
40 #include <objectformatter.hxx>
41 #include <ndole.hxx>
42 #include <swtable.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdoashp.hxx>
45 #include <layouter.hxx>
46 #include <pagefrm.hxx>
47 #include <rootfrm.hxx>
48 #include <viewimp.hxx>
49 #include <viewopt.hxx>
50 #include <dcontact.hxx>
51 #include <dflyobj.hxx>
52 #include <dview.hxx>
53 #include <frmatr.hxx>
54 #include <frmtool.hxx>
55 #include <hints.hxx>
56 #include <tabfrm.hxx>
57 #include <txtfrm.hxx>
58 #include <notxtfrm.hxx>
59 #include <flyfrms.hxx>
60 #include <sectfrm.hxx>
61 #include <vcl/svapp.hxx>
62 #include <calbck.hxx>
63 #include <IDocumentDrawModelAccess.hxx>
64 #include <IDocumentSettingAccess.hxx>
65 #include <IDocumentLayoutAccess.hxx>
66 #include <textboxhelper.hxx>
67 #include <txtfly.hxx>
68 #include <ndindex.hxx>
69 #include <pam.hxx>
70 #include <basegfx/polygon/b2dpolygontools.hxx>
71 #include <basegfx/matrix/b2dhommatrixtools.hxx>
72 
73 #include <wrtsh.hxx>
74 #include <view.hxx>
75 #include <edtwin.hxx>
76 #include <bodyfrm.hxx>
77 #include <FrameControlsManager.hxx>
78 #include <ndtxt.hxx>
79 
80 using namespace ::com::sun::star;
81 
82 static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame );
83 
SwFlyFrame(SwFlyFrameFormat * pFormat,SwFrame * pSib,SwFrame * pAnch)84 SwFlyFrame::SwFlyFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) :
85     SwLayoutFrame( pFormat, pSib ),
86     SwAnchoredObject(), // #i26791#
87     m_pPrevLink( nullptr ),
88     m_pNextLink( nullptr ),
89     m_bInCnt( false ),
90     m_bAtCnt( false ),
91     m_bLayout( false ),
92     m_bAutoPosition( false ),
93     m_bValidContentPos( false )
94 {
95     mnFrameType = SwFrameType::Fly;
96 
97     m_bInvalid = m_bNotifyBack = true;
98     m_bLocked  = m_bMinHeight =
99     m_bHeightClipped = m_bWidthClipped = m_bFormatHeightOnly = false;
100 
101     // Size setting: Fixed size is always the width
102     const SwFormatFrameSize &rFrameSize = pFormat->GetFrameSize();
103     const SvxFrameDirection nDir = pFormat->GetFormatAttr( RES_FRAMEDIR ).GetValue();
104     if( SvxFrameDirection::Environment == nDir )
105     {
106         mbDerivedVert = true;
107         mbDerivedR2L = true;
108     }
109     else
110     {
111         mbInvalidVert = false;
112         mbDerivedVert = false;
113         mbDerivedR2L = false;
114         if( SvxFrameDirection::Horizontal_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir )
115         {
116             mbVertLR = false;
117             mbVertical = false;
118         }
119         else
120         {
121             const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
122             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
123             {
124                 mbVertLR = false;
125                 mbVertical = false;
126             }
127             else
128             {
129                 mbVertical = true;
130 
131                 if ( SvxFrameDirection::Vertical_LR_TB == nDir )
132                     mbVertLR = true;
133                 else if (nDir == SvxFrameDirection::Vertical_LR_BT)
134                 {
135                     mbVertLR = true;
136                     mbVertLRBT = true;
137                 }
138                 else
139                     mbVertLR = false;
140             }
141         }
142 
143         mbInvalidR2L = false;
144         if( SvxFrameDirection::Horizontal_RL_TB == nDir )
145             mbRightToLeft = true;
146         else
147             mbRightToLeft = false;
148     }
149 
150     {
151         SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
152         aFrm.Width( rFrameSize.GetWidth() );
153         aFrm.Height( rFrameSize.GetHeightSizeType() == ATT_VAR_SIZE ? MINFLY : rFrameSize.GetHeight() );
154     }
155 
156     // Fixed or variable Height?
157     if ( rFrameSize.GetHeightSizeType() == ATT_MIN_SIZE )
158         m_bMinHeight = true;
159     else if ( rFrameSize.GetHeightSizeType() == ATT_FIX_SIZE )
160         mbFixSize = true;
161 
162     // insert columns, if necessary
163     InsertColumns();
164 
165     // First the Init, then the Content:
166     // This is due to the fact that the Content may have Objects/Frames,
167     // which are then registered
168     InitDrawObj();
169 
170     Chain( pAnch );
171 
172     InsertCnt();
173 
174     // Put it somewhere outside so that out document is not formatted unnecessarily often
175     SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
176     aFrm.Pos().setX(FAR_AWAY);
177     aFrm.Pos().setY(FAR_AWAY);
178 }
179 
Chain(SwFrame * _pAnch)180 void SwFlyFrame::Chain( SwFrame* _pAnch )
181 {
182     // Connect to chain neighbours.
183     // No problem, if a neighbor doesn't exist - the construction of the
184     // neighbor will make the connection
185     const SwFormatChain& rChain = GetFormat()->GetChain();
186     if ( rChain.GetPrev() || rChain.GetNext() )
187     {
188         if ( rChain.GetNext() )
189         {
190             SwFlyFrame* pFollow = FindChainNeighbour( *rChain.GetNext(), _pAnch );
191             if ( pFollow )
192             {
193                 OSL_ENSURE( !pFollow->GetPrevLink(), "wrong chain detected" );
194                 if ( !pFollow->GetPrevLink() )
195                     SwFlyFrame::ChainFrames( this, pFollow );
196             }
197         }
198         if ( rChain.GetPrev() )
199         {
200             SwFlyFrame *pMaster = FindChainNeighbour( *rChain.GetPrev(), _pAnch );
201             if ( pMaster )
202             {
203                 OSL_ENSURE( !pMaster->GetNextLink(), "wrong chain detected" );
204                 if ( !pMaster->GetNextLink() )
205                     SwFlyFrame::ChainFrames( pMaster, this );
206             }
207         }
208     }
209 }
210 
InsertCnt()211 void SwFlyFrame::InsertCnt()
212 {
213     if ( !GetPrevLink() )
214     {
215         const SwFormatContent& rContent = GetFormat()->GetContent();
216         OSL_ENSURE( rContent.GetContentIdx(), ":-( no content prepared." );
217         sal_uLong nIndex = rContent.GetContentIdx()->GetIndex();
218         // Lower() means SwColumnFrame; the Content then needs to be inserted into the (Column)BodyFrame
219         ::InsertCnt_( Lower() ? static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(Lower())->Lower()) : static_cast<SwLayoutFrame*>(this),
220                       GetFormat()->GetDoc(), nIndex );
221 
222         // NoText always have a fixed height.
223         if ( Lower() && Lower()->IsNoTextFrame() )
224         {
225             mbFixSize = true;
226             m_bMinHeight = false;
227         }
228     }
229 }
230 
InsertColumns()231 void SwFlyFrame::InsertColumns()
232 {
233     // #i97379#
234     // Check, if column are allowed.
235     // Columns are not allowed for fly frames, which represent graphics or embedded objects.
236     const SwFormatContent& rContent = GetFormat()->GetContent();
237     OSL_ENSURE( rContent.GetContentIdx(), "<SwFlyFrame::InsertColumns()> - no content prepared." );
238     SwNodeIndex aFirstContent( *(rContent.GetContentIdx()), 1 );
239     if ( aFirstContent.GetNode().IsNoTextNode() )
240     {
241         return;
242     }
243 
244     const SwFormatCol &rCol = GetFormat()->GetCol();
245     if ( rCol.GetNumCols() > 1 )
246     {
247         // Start off PrtArea to be as large as Frame, so that we can put in the columns
248         // properly. It'll adjust later on.
249         {
250             SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
251             aPrt.Width( getFrameArea().Width() );
252             aPrt.Height( getFrameArea().Height() );
253         }
254 
255         const SwFormatCol aOld; // ChgColumns() also needs an old value passed
256         ChgColumns( aOld, rCol );
257     }
258 }
259 
DestroyImpl()260 void SwFlyFrame::DestroyImpl()
261 {
262     // Accessible objects for fly frames will be destroyed in this destructor.
263     // For frames bound as char or frames that don't have an anchor we have
264     // to do that ourselves. For any other frame the call RemoveFly at the
265     // anchor will do that.
266     if( IsAccessibleFrame() && GetFormat() && (IsFlyInContentFrame() || !GetAnchorFrame()) )
267     {
268         SwRootFrame *pRootFrame = getRootFrame();
269         if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
270         {
271             SwViewShell *pVSh = pRootFrame->GetCurrShell();
272             if( pVSh && pVSh->Imp() )
273             {
274                 // Lowers aren't disposed already, so we have to do a recursive
275                 // dispose
276                 pVSh->Imp()->DisposeAccessibleFrame( this, true );
277             }
278         }
279     }
280 
281     if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() )
282     {
283         ClearTmpConsiderWrapInfluence(); // remove this from SwLayouter
284 
285         // OD 2004-01-19 #110582#
286         Unchain();
287 
288         // OD 2004-01-19 #110582#
289         DeleteCnt();
290 
291         if ( GetAnchorFrame() )
292             AnchorFrame()->RemoveFly( this );
293     }
294 
295     FinitDrawObj();
296 
297     SwLayoutFrame::DestroyImpl();
298 
299     SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(getRootFrame()->GetCurrShell());
300     UpdateUnfloatButton(pWrtSh, false);
301 }
302 
~SwFlyFrame()303 SwFlyFrame::~SwFlyFrame()
304 {
305 }
306 
getIDocumentDrawModelAccess()307 const IDocumentDrawModelAccess& SwFlyFrame::getIDocumentDrawModelAccess()
308 {
309     return GetFormat()->getIDocumentDrawModelAccess();
310 }
311 
312 // OD 2004-01-19 #110582#
Unchain()313 void SwFlyFrame::Unchain()
314 {
315     if ( GetPrevLink() )
316         UnchainFrames( GetPrevLink(), this );
317     if ( GetNextLink() )
318         UnchainFrames( this, GetNextLink() );
319 }
320 
321 // OD 2004-01-19 #110582#
DeleteCnt()322 void SwFlyFrame::DeleteCnt()
323 {
324     SwFrame* pFrame = m_pLower;
325     while ( pFrame )
326     {
327         while ( pFrame->GetDrawObjs() && pFrame->GetDrawObjs()->size() )
328         {
329             SwAnchoredObject *pAnchoredObj = (*pFrame->GetDrawObjs())[0];
330             if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) !=  nullptr )
331             {
332                 SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj));
333             }
334             else if ( dynamic_cast<const SwAnchoredDrawObject*>( pAnchoredObj) !=  nullptr )
335             {
336                 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
337                 SdrObject* pObj = pAnchoredObj->DrawObj();
338                 if ( dynamic_cast<const SwDrawVirtObj*>( pObj) !=  nullptr )
339                 {
340                     SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pObj);
341                     pDrawVirtObj->RemoveFromWriterLayout();
342                     pDrawVirtObj->RemoveFromDrawingPage();
343                 }
344                 else
345                 {
346                     SwDrawContact* pContact =
347                             static_cast<SwDrawContact*>(::GetUserCall( pObj ));
348                     if ( pContact )
349                     {
350                         pContact->DisconnectFromLayout();
351                     }
352                 }
353             }
354         }
355 
356         pFrame->RemoveFromLayout();
357         SwFrame::DestroyFrame(pFrame);
358         pFrame = m_pLower;
359     }
360 
361     InvalidatePage();
362 }
363 
InitDrawObj()364 void SwFlyFrame::InitDrawObj()
365 {
366     // OD 2004-03-22 #i26791#
367     SetDrawObj(*SwFlyDrawContact::CreateNewRef(this, GetFormat()));
368 
369     // Set the right Layer
370     // OD 2004-01-19 #110582#
371     IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
372     SdrLayerID nHeavenId = rIDDMA.GetHeavenId();
373     SdrLayerID nHellId = rIDDMA.GetHellId();
374     // OD 2004-03-22 #i26791#
375     GetVirtDrawObj()->SetLayer( GetFormat()->GetOpaque().GetValue()
376                                 ? nHeavenId
377                                 : nHellId );
378 }
379 
FinitDrawObj()380 void SwFlyFrame::FinitDrawObj()
381 {
382     if(!GetVirtDrawObj() )
383         return;
384     SwFormat* pFormat = GetFormat();
385     // Deregister from SdrPageViews if the Objects is still selected there.
386     if(!pFormat->GetDoc()->IsInDtor())
387     {
388         SwViewShell* p1St = getRootFrame()->GetCurrShell();
389         if(p1St)
390         {
391             for(SwViewShell& rCurrentShell : p1St->GetRingContainer())
392             {   // At the moment the Drawing can do just do an Unmark on everything,
393                 // as the Object was already removed
394                 if(rCurrentShell.HasDrawView() )
395                     rCurrentShell.Imp()->GetDrawView()->UnmarkAll();
396             }
397         }
398     }
399 
400     // Else calls delete of the ContactObj
401     GetVirtDrawObj()->SetUserCall(nullptr);
402 
403     // Deregisters itself at the Master
404     // always use SdrObject::Free(...) for SdrObjects (!)
405     SdrObject* pTemp(GetVirtDrawObj());
406     SdrObject::Free(pTemp);
407 }
408 
ChainFrames(SwFlyFrame * pMaster,SwFlyFrame * pFollow)409 void SwFlyFrame::ChainFrames( SwFlyFrame *pMaster, SwFlyFrame *pFollow )
410 {
411     OSL_ENSURE( pMaster && pFollow, "incomplete chain" );
412     OSL_ENSURE( !pMaster->GetNextLink(), "link can not be changed" );
413     OSL_ENSURE( !pFollow->GetPrevLink(), "link can not be changed" );
414 
415     pMaster->m_pNextLink = pFollow;
416     pFollow->m_pPrevLink = pMaster;
417 
418     if ( pMaster->ContainsContent() )
419     {
420         // To get a text flow we need to invalidate
421         SwFrame *pInva = pMaster->FindLastLower();
422         SwRectFnSet aRectFnSet(pMaster);
423         const long nBottom = aRectFnSet.GetPrtBottom(*pMaster);
424         while ( pInva )
425         {
426             if( aRectFnSet.BottomDist( pInva->getFrameArea(), nBottom ) <= 0 )
427             {
428                 pInva->InvalidateSize();
429                 pInva->Prepare();
430                 pInva = pInva->FindPrev();
431             }
432             else
433                 pInva = nullptr;
434         }
435     }
436 
437     if ( pFollow->ContainsContent() )
438     {
439         // There's only the content from the Masters left; the content from the Follow
440         // does not have any Frames left (should always be exactly one empty TextNode).
441         SwFrame *pFrame = pFollow->ContainsContent();
442         OSL_ENSURE( !pFrame->IsTabFrame() && !pFrame->FindNext(), "follow in chain contains content" );
443         pFrame->Cut();
444         SwFrame::DestroyFrame(pFrame);
445     }
446 
447     // invalidate accessible relation set (accessibility wrapper)
448     SwViewShell* pSh = pMaster->getRootFrame()->GetCurrShell();
449     if( pSh )
450     {
451         SwRootFrame* pLayout = pMaster->getRootFrame();
452         if( pLayout && pLayout->IsAnyShellAccessible() )
453             pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
454     }
455 }
456 
UnchainFrames(SwFlyFrame * pMaster,SwFlyFrame * pFollow)457 void SwFlyFrame::UnchainFrames( SwFlyFrame *pMaster, SwFlyFrame *pFollow )
458 {
459     pMaster->m_pNextLink = nullptr;
460     pFollow->m_pPrevLink = nullptr;
461 
462     if ( pFollow->ContainsContent() )
463     {
464         // The Master sucks up the content of the Follow
465         SwLayoutFrame *pUpper = pMaster;
466         if ( pUpper->Lower()->IsColumnFrame() )
467         {
468             pUpper = static_cast<SwLayoutFrame*>(pUpper->GetLastLower());
469             pUpper = static_cast<SwLayoutFrame*>(pUpper->Lower()); // The (Column)BodyFrame
470             OSL_ENSURE( pUpper && pUpper->IsColBodyFrame(), "Missing ColumnBody" );
471         }
472         SwFlyFrame *pFoll = pFollow;
473         while ( pFoll )
474         {
475             SwFrame *pTmp = ::SaveContent( pFoll );
476             if ( pTmp )
477                 ::RestoreContent( pTmp, pUpper, pMaster->FindLastLower() );
478             pFoll->SetCompletePaint();
479             pFoll->InvalidateSize();
480             pFoll = pFoll->GetNextLink();
481         }
482     }
483 
484     // The Follow needs his own content to be served
485     const SwFormatContent &rContent = pFollow->GetFormat()->GetContent();
486     OSL_ENSURE( rContent.GetContentIdx(), ":-( No content prepared." );
487     sal_uLong nIndex = rContent.GetContentIdx()->GetIndex();
488     // Lower() means SwColumnFrame: this one contains another SwBodyFrame
489     ::InsertCnt_( pFollow->Lower() ? const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFollow->Lower())->Lower()))
490                                    : static_cast<SwLayoutFrame*>(pFollow),
491                   pFollow->GetFormat()->GetDoc(), ++nIndex );
492 
493     // invalidate accessible relation set (accessibility wrapper)
494     SwViewShell* pSh = pMaster->getRootFrame()->GetCurrShell();
495     if( pSh )
496     {
497         SwRootFrame* pLayout = pMaster->getRootFrame();
498         if( pLayout && pLayout->IsAnyShellAccessible() )
499             pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
500     }
501 }
502 
FindChainNeighbour(SwFrameFormat const & rChain,SwFrame * pAnch)503 SwFlyFrame *SwFlyFrame::FindChainNeighbour( SwFrameFormat const &rChain, SwFrame *pAnch )
504 {
505     // We look for the Fly that's in the same Area.
506     // Areas can for now only be Head/Footer or Flys.
507 
508     if ( !pAnch ) // If an Anchor was passed along, that one counts (ctor!)
509         pAnch = AnchorFrame();
510 
511     SwLayoutFrame *pLay;
512     if ( pAnch->IsInFly() )
513         pLay = pAnch->FindFlyFrame();
514     else
515     {
516         // FindFooterOrHeader is not appropriate here, as we may not have a
517         // connection to the Anchor yet.
518         pLay = pAnch->GetUpper();
519         while ( pLay && !(pLay->GetType() & (SwFrameType::Header|SwFrameType::Footer)) )
520             pLay = pLay->GetUpper();
521     }
522 
523     SwIterator<SwFlyFrame,SwFormat> aIter( rChain );
524     SwFlyFrame *pFly = aIter.First();
525     if ( pLay )
526     {
527         while ( pFly )
528         {
529             if ( pFly->GetAnchorFrame() )
530             {
531                 if ( pFly->GetAnchorFrame()->IsInFly() )
532                 {
533                     if ( pFly->AnchorFrame()->FindFlyFrame() == pLay )
534                         break;
535                 }
536                 else if ( pLay == pFly->FindFooterOrHeader() )
537                     break;
538             }
539             pFly = aIter.Next();
540         }
541     }
542     else if ( pFly )
543     {
544         OSL_ENSURE( !aIter.Next(), "chain with more than one instance" );
545     }
546     return pFly;
547 }
548 
FindLastLower()549 SwFrame *SwFlyFrame::FindLastLower()
550 {
551     SwFrame *pRet = ContainsAny();
552     if ( pRet && pRet->IsInTab() )
553         pRet = pRet->FindTabFrame();
554     SwFrame *pNxt = pRet;
555     while ( pNxt && IsAnLower( pNxt ) )
556     {   pRet = pNxt;
557         pNxt = pNxt->FindNext();
558     }
559     return pRet;
560 }
561 
FrameSizeChg(const SwFormatFrameSize & rFrameSize)562 bool SwFlyFrame::FrameSizeChg( const SwFormatFrameSize &rFrameSize )
563 {
564     bool bRet = false;
565     SwTwips nDiffHeight = getFrameArea().Height();
566     if ( rFrameSize.GetHeightSizeType() == ATT_VAR_SIZE )
567         mbFixSize = m_bMinHeight = false;
568     else
569     {
570         if ( rFrameSize.GetHeightSizeType() == ATT_FIX_SIZE )
571         {
572             mbFixSize = true;
573             m_bMinHeight = false;
574         }
575         else if ( rFrameSize.GetHeightSizeType() == ATT_MIN_SIZE )
576         {
577             mbFixSize = false;
578             m_bMinHeight = true;
579         }
580         nDiffHeight -= rFrameSize.GetHeight();
581     }
582     // If the Fly contains columns, we already need to set the Fly
583     // and the Columns to the required value or else we run into problems.
584     if ( Lower() )
585     {
586         if ( Lower()->IsColumnFrame() )
587         {
588             const SwRect aOld( GetObjRectWithSpaces() );
589             const Size   aOldSz( getFramePrintArea().SSize() );
590             const SwTwips nDiffWidth = getFrameArea().Width() - rFrameSize.GetWidth();
591 
592             {
593                 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
594                 aFrm.Height( aFrm.Height() - nDiffHeight );
595                 aFrm.Width ( aFrm.Width()  - nDiffWidth  );
596             }
597 
598             // #i68520#
599             InvalidateObjRectWithSpaces();
600 
601             {
602                 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
603                 aPrt.Height( aPrt.Height() - nDiffHeight );
604                 aPrt.Width ( aPrt.Width()  - nDiffWidth  );
605             }
606 
607             ChgLowersProp( aOldSz );
608             ::Notify( this, FindPageFrame(), aOld );
609             setFrameAreaPositionValid(false);
610             bRet = true;
611         }
612         else if ( Lower()->IsNoTextFrame() )
613         {
614             mbFixSize = true;
615             m_bMinHeight = false;
616         }
617     }
618     return bRet;
619 }
620 
SwClientNotify(const SwModify & rMod,const SfxHint & rHint)621 void SwFlyFrame::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
622 {
623     SwFrame::SwClientNotify(rMod, rHint);
624     if (auto pGetZOrdnerHint = dynamic_cast<const sw::GetZOrderHint*>(&rHint))
625     {
626         const auto& rFormat(dynamic_cast<const SwFrameFormat&>(rMod));
627         if (rFormat.Which() == RES_FLYFRMFMT && rFormat.getIDocumentLayoutAccess().GetCurrentViewShell()) // #i11176#
628             pGetZOrdnerHint->m_rnZOrder = GetVirtDrawObj()->GetOrdNum();
629     }
630     else if (auto pConnectedHint = dynamic_cast<const sw::GetObjectConnectedHint*>(&rHint))
631     {
632         const auto& rFormat(dynamic_cast<const SwFrameFormat&>(rMod));
633         if (!pConnectedHint->m_risConnected && rFormat.Which() == RES_FLYFRMFMT && (!pConnectedHint->m_pRoot || pConnectedHint->m_pRoot == getRootFrame()))
634             pConnectedHint->m_risConnected = true;
635     }
636 }
637 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)638 void SwFlyFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
639 {
640     sal_uInt8 nInvFlags = 0;
641 
642     if (pNew && pOld && RES_ATTRSET_CHG == pNew->Which())
643     {
644         SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() );
645         SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
646         const SfxPoolItem* pNItem = aNIter.GetCurItem();
647         const SfxPoolItem* pOItem = aOIter.GetCurItem();
648         SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
649         SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
650         do
651         {
652             UpdateAttr_(pOItem, pNItem, nInvFlags, &aOldSet, &aNewSet);
653             pNItem = aNIter.NextItem();
654             pOItem = aOIter.NextItem();
655         } while (pNItem);
656         if ( aOldSet.Count() || aNewSet.Count() )
657             SwLayoutFrame::Modify( &aOldSet, &aNewSet );
658     }
659     else
660         UpdateAttr_( pOld, pNew, nInvFlags );
661 
662     if ( nInvFlags == 0 )
663         return;
664 
665     Invalidate_();
666     if ( nInvFlags & 0x01 )
667     {
668         InvalidatePos_();
669         // #i68520#
670         InvalidateObjRectWithSpaces();
671     }
672     if ( nInvFlags & 0x02 )
673     {
674         InvalidateSize_();
675         // #i68520#
676         InvalidateObjRectWithSpaces();
677     }
678     if ( nInvFlags & 0x04 )
679         InvalidatePrt_();
680     if ( nInvFlags & 0x08 )
681         SetNotifyBack();
682     if ( nInvFlags & 0x10 )
683         SetCompletePaint();
684     if ( ( nInvFlags & 0x40 ) && Lower() && Lower()->IsNoTextFrame() )
685         ClrContourCache( GetVirtDrawObj() );
686     SwRootFrame *pRoot;
687     if ( nInvFlags & 0x20 && nullptr != (pRoot = getRootFrame()) )
688         pRoot->InvalidateBrowseWidth();
689     // #i28701#
690     if ( nInvFlags & 0x80 )
691     {
692         // update sorted object lists, the Writer fly frame is registered at.
693         UpdateObjInSortedList();
694     }
695 
696     // #i87645# - reset flags for the layout process (only if something has been invalidated)
697     ResetLayoutProcessBools();
698 
699 }
700 
UpdateAttr_(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags,SwAttrSetChg * pOldSet,SwAttrSetChg * pNewSet)701 void SwFlyFrame::UpdateAttr_( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
702                             sal_uInt8 &rInvFlags,
703                             SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
704 {
705     bool bClear = true;
706     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
707     SwViewShell *pSh = getRootFrame()->GetCurrShell();
708     switch( nWhich )
709     {
710         case RES_VERT_ORIENT:
711         case RES_HORI_ORIENT:
712         // OD 22.09.2003 #i18732# - consider new option 'follow text flow'
713         case RES_FOLLOW_TEXT_FLOW:
714         {
715             // ATTENTION: Always also change Action in ChgRePos()!
716             rInvFlags |= 0x09;
717         }
718         break;
719         // OD 2004-07-01 #i28701# - consider new option 'wrap influence on position'
720         case RES_WRAP_INFLUENCE_ON_OBJPOS:
721         {
722             rInvFlags |= 0x89;
723         }
724         break;
725         case RES_SURROUND:
726         {
727             // OD 2004-05-13 #i28701# - invalidate position on change of
728             // wrapping style.
729             //rInvFlags |= 0x40;
730             rInvFlags |= 0x41;
731             // The background needs to be messaged and invalidated
732             const SwRect aTmp( GetObjRectWithSpaces() );
733             NotifyBackground( FindPageFrame(), aTmp, PREP_FLY_ATTR_CHG );
734 
735             // By changing the flow of frame-bound Frames, a vertical alignment
736             // can be activated/deactivated => MakeFlyPos
737             if( RndStdIds::FLY_AT_FLY == GetFormat()->GetAnchor().GetAnchorId() )
738                 rInvFlags |= 0x09;
739 
740             // Delete contour in the Node if necessary
741             if ( Lower() && Lower()->IsNoTextFrame() &&
742                  !GetFormat()->GetSurround().IsContour() )
743             {
744                 SwNoTextNode *pNd = static_cast<SwNoTextNode*>(static_cast<SwNoTextFrame*>(Lower())->GetNode());
745                 if ( pNd->HasContour() )
746                     pNd->SetContour( nullptr );
747             }
748             // #i28701# - perform reorder of object lists
749             // at anchor frame and at page frame.
750             rInvFlags |= 0x80;
751         }
752         break;
753 
754         case RES_PROTECT:
755             if (pNew)
756             {
757                 const SvxProtectItem *pP = static_cast<const SvxProtectItem*>(pNew);
758                 GetVirtDrawObj()->SetMoveProtect( pP->IsPosProtected()   );
759                 GetVirtDrawObj()->SetResizeProtect( pP->IsSizeProtected() );
760                 if( pSh )
761                 {
762                     SwRootFrame* pLayout = getRootFrame();
763                     if( pLayout && pLayout->IsAnyShellAccessible() )
764                         pSh->Imp()->InvalidateAccessibleEditableState( true, this );
765                 }
766             }
767             break;
768         case RES_COL:
769             if (pOld && pNew)
770             {
771                 ChgColumns( *static_cast<const SwFormatCol*>(pOld), *static_cast<const SwFormatCol*>(pNew) );
772                 const SwFormatFrameSize &rNew = GetFormat()->GetFrameSize();
773                 if ( FrameSizeChg( rNew ) )
774                     NotifyDrawObj();
775                 rInvFlags |= 0x1A;
776             }
777             break;
778 
779         case RES_FRM_SIZE:
780         case RES_FMT_CHG:
781         {
782             const SwFormatFrameSize &rNew = GetFormat()->GetFrameSize();
783             if ( FrameSizeChg( rNew ) )
784                 NotifyDrawObj();
785             rInvFlags |= 0x7F;
786             if (pOld && RES_FMT_CHG == nWhich)
787             {
788                 SwRect aNew( GetObjRectWithSpaces() );
789                 SwRect aOld( getFrameArea() );
790                 const SvxULSpaceItem &rUL = static_cast<const SwFormatChg*>(pOld)->pChangedFormat->GetULSpace();
791                 aOld.Top( std::max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
792                 aOld.SSize().AdjustHeight(rUL.GetLower() );
793                 const SvxLRSpaceItem &rLR = static_cast<const SwFormatChg*>(pOld)->pChangedFormat->GetLRSpace();
794                 aOld.Left  ( std::max( aOld.Left() - rLR.GetLeft(), 0L ) );
795                 aOld.SSize().AdjustWidth(rLR.GetRight() );
796                 aNew.Union( aOld );
797                 NotifyBackground( FindPageFrame(), aNew, PREP_CLEAR );
798 
799                 // Special case:
800                 // When assigning a template we cannot rely on the old column
801                 // attribute. As there need to be at least enough for ChgColumns,
802                 // we need to create a temporary attribute.
803                 SwFormatCol aCol;
804                 if ( Lower() && Lower()->IsColumnFrame() )
805                 {
806                     sal_uInt16 nCol = 0;
807                     SwFrame *pTmp = Lower();
808                     do
809                     {   ++nCol;
810                         pTmp = pTmp->GetNext();
811                     } while ( pTmp );
812                     aCol.Init( nCol, 0, 1000 );
813                 }
814                 ChgColumns( aCol, GetFormat()->GetCol() );
815             }
816 
817             SwFormatURL aURL( GetFormat()->GetURL() );
818 
819             SwFormatFrameSize *pNewFormatFrameSize = nullptr;
820             SwFormatChg *pOldFormatChg = nullptr;
821             if (nWhich == RES_FRM_SIZE)
822                 pNewFormatFrameSize = const_cast<SwFormatFrameSize*>(static_cast<const SwFormatFrameSize*>(pNew));
823             else
824                 pOldFormatChg = const_cast<SwFormatChg*>(static_cast<const SwFormatChg*>(pOld));
825 
826             if (aURL.GetMap() && (pNewFormatFrameSize || pOldFormatChg))
827             {
828                 const SwFormatFrameSize &rOld = pNewFormatFrameSize ?
829                                 *pNewFormatFrameSize :
830                                 pOldFormatChg->pChangedFormat->GetFrameSize();
831                 //#35091# Can be "times zero", when loading the template
832                 if ( rOld.GetWidth() && rOld.GetHeight() )
833                 {
834 
835                     Fraction aScaleX( rOld.GetWidth(), rNew.GetWidth() );
836                     Fraction aScaleY( rOld.GetHeight(), rOld.GetHeight() );
837                     aURL.GetMap()->Scale( aScaleX, aScaleY );
838                     SwFrameFormat *pFormat = GetFormat();
839                     pFormat->LockModify();
840                     pFormat->SetFormatAttr( aURL );
841                     pFormat->UnlockModify();
842                 }
843             }
844             const SvxProtectItem &rP = GetFormat()->GetProtect();
845             GetVirtDrawObj()->SetMoveProtect( rP.IsPosProtected()    );
846             GetVirtDrawObj()->SetResizeProtect( rP.IsSizeProtected() );
847 
848             if ( pSh )
849                 pSh->InvalidateWindows( getFrameArea() );
850             const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
851             const SdrLayerID nId = GetFormat()->GetOpaque().GetValue() ?
852                              rIDDMA.GetHeavenId() :
853                              rIDDMA.GetHellId();
854             GetVirtDrawObj()->SetLayer( nId );
855 
856             if ( Lower() )
857             {
858                 // Delete contour in the Node if necessary
859                 if( Lower()->IsNoTextFrame() &&
860                      !GetFormat()->GetSurround().IsContour() )
861                 {
862                     SwNoTextNode *pNd = static_cast<SwNoTextNode*>(static_cast<SwNoTextFrame*>(Lower())->GetNode());
863                     if ( pNd->HasContour() )
864                         pNd->SetContour( nullptr );
865                 }
866                 else if( !Lower()->IsColumnFrame() )
867                 {
868                     SwFrame* pFrame = GetLastLower();
869                     if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
870                         pFrame->Prepare( PREP_ADJUST_FRM );
871                 }
872             }
873 
874             // #i28701# - perform reorder of object lists
875             // at anchor frame and at page frame.
876             rInvFlags |= 0x80;
877 
878             break;
879         }
880         case RES_UL_SPACE:
881         case RES_LR_SPACE:
882         {
883             rInvFlags |= 0x41;
884             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
885                 getRootFrame()->InvalidateBrowseWidth();
886             SwRect aNew( GetObjRectWithSpaces() );
887             SwRect aOld( getFrameArea() );
888             if (pNew)
889             {
890                 if ( RES_UL_SPACE == nWhich )
891                 {
892                     const SvxULSpaceItem &rUL = *static_cast<const SvxULSpaceItem*>(pNew);
893                     aOld.Top( std::max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
894                     aOld.SSize().AdjustHeight(rUL.GetLower() );
895                 }
896                 else
897                 {
898                     const SvxLRSpaceItem &rLR = *static_cast<const SvxLRSpaceItem*>(pNew);
899                     aOld.Left  ( std::max( aOld.Left() - rLR.GetLeft(), 0L ) );
900                     aOld.SSize().AdjustWidth(rLR.GetRight() );
901                 }
902             }
903             aNew.Union( aOld );
904             NotifyBackground( FindPageFrame(), aNew, PREP_CLEAR );
905         }
906         break;
907 
908         case RES_TEXT_VERT_ADJUST:
909         {
910             InvalidateContentPos();
911             rInvFlags |= 0x10;
912         }
913         break;
914 
915         case RES_BOX:
916         case RES_SHADOW:
917             rInvFlags |= 0x17;
918             break;
919 
920         case RES_FRAMEDIR :
921             SetDerivedVert( false );
922             SetDerivedR2L( false );
923             CheckDirChange();
924             break;
925 
926         case RES_OPAQUE:
927             {
928                 if ( pSh )
929                     pSh->InvalidateWindows( getFrameArea() );
930 
931                 const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
932                 const SdrLayerID nId = static_cast<const SvxOpaqueItem*>(pNew)->GetValue() ?
933                                     rIDDMA.GetHeavenId() :
934                                     rIDDMA.GetHellId();
935                 GetVirtDrawObj()->SetLayer( nId );
936                 if( pSh )
937                 {
938                     SwRootFrame* pLayout = getRootFrame();
939                     if( pLayout && pLayout->IsAnyShellAccessible() )
940                 {
941                     pSh->Imp()->DisposeAccessibleFrame( this );
942                     pSh->Imp()->AddAccessibleFrame( this );
943                 }
944                 }
945                 // #i28701# - perform reorder of object lists
946                 // at anchor frame and at page frame.
947                 rInvFlags |= 0x80;
948             }
949             break;
950 
951         case RES_URL:
952             // The interface changes the frame size when interacting with text frames,
953             // the Map, however, needs to be relative to FrameSize().
954             if ( (!Lower() || !Lower()->IsNoTextFrame()) && pNew && pOld &&
955                  static_cast<const SwFormatURL*>(pNew)->GetMap() && static_cast<const SwFormatURL*>(pOld)->GetMap() )
956             {
957                 const SwFormatFrameSize &rSz = GetFormat()->GetFrameSize();
958                 if ( rSz.GetHeight() != getFrameArea().Height() ||
959                      rSz.GetWidth()  != getFrameArea().Width() )
960                 {
961                     SwFormatURL aURL( GetFormat()->GetURL() );
962                     Fraction aScaleX( getFrameArea().Width(),  rSz.GetWidth() );
963                     Fraction aScaleY( getFrameArea().Height(), rSz.GetHeight() );
964                     aURL.GetMap()->Scale( aScaleX, aScaleY );
965                     SwFrameFormat *pFormat = GetFormat();
966                     pFormat->LockModify();
967                     pFormat->SetFormatAttr( aURL );
968                     pFormat->UnlockModify();
969                 }
970             }
971             // No invalidation necessary
972             break;
973 
974         case RES_CHAIN:
975             if (pNew)
976             {
977                 const SwFormatChain *pChain = static_cast<const SwFormatChain*>(pNew);
978                 if ( pChain->GetNext() )
979                 {
980                     SwFlyFrame *pFollow = FindChainNeighbour( *pChain->GetNext() );
981                     if ( GetNextLink() && pFollow != GetNextLink() )
982                         SwFlyFrame::UnchainFrames( this, GetNextLink());
983                     if ( pFollow )
984                     {
985                         if ( pFollow->GetPrevLink() &&
986                              pFollow->GetPrevLink() != this )
987                             SwFlyFrame::UnchainFrames( pFollow->GetPrevLink(),
988                                                      pFollow );
989                         if ( !GetNextLink() )
990                             SwFlyFrame::ChainFrames( this, pFollow );
991                     }
992                 }
993                 else if ( GetNextLink() )
994                     SwFlyFrame::UnchainFrames( this, GetNextLink() );
995                 if ( pChain->GetPrev() )
996                 {
997                     SwFlyFrame *pMaster = FindChainNeighbour( *pChain->GetPrev() );
998                     if ( GetPrevLink() && pMaster != GetPrevLink() )
999                         SwFlyFrame::UnchainFrames( GetPrevLink(), this );
1000                     if ( pMaster )
1001                     {
1002                         if ( pMaster->GetNextLink() &&
1003                              pMaster->GetNextLink() != this )
1004                             SwFlyFrame::UnchainFrames( pMaster,
1005                                                      pMaster->GetNextLink() );
1006                         if ( !GetPrevLink() )
1007                             SwFlyFrame::ChainFrames( pMaster, this );
1008                     }
1009                 }
1010                 else if ( GetPrevLink() )
1011                     SwFlyFrame::UnchainFrames( GetPrevLink(), this );
1012             }
1013             [[fallthrough]];
1014         default:
1015             bClear = false;
1016     }
1017     if ( bClear )
1018     {
1019         if ( pOldSet || pNewSet )
1020         {
1021             if ( pOldSet )
1022                 pOldSet->ClearItem( nWhich );
1023             if ( pNewSet )
1024                 pNewSet->ClearItem( nWhich );
1025         }
1026         else
1027             SwLayoutFrame::Modify( pOld, pNew );
1028     }
1029 }
1030 
1031 /// Gets information from the Modify
GetInfo(SfxPoolItem & rInfo) const1032 bool SwFlyFrame::GetInfo( SfxPoolItem & rInfo ) const
1033 {
1034     if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
1035         return false;   // There's a FlyFrame, so use it
1036     return true;        // Continue searching
1037 }
1038 
Invalidate_(SwPageFrame const * pPage)1039 void SwFlyFrame::Invalidate_( SwPageFrame const *pPage )
1040 {
1041     InvalidatePage( pPage );
1042     m_bNotifyBack = m_bInvalid = true;
1043 
1044     SwFlyFrame *pFrame;
1045     if ( GetAnchorFrame() && nullptr != (pFrame = AnchorFrame()->FindFlyFrame()) )
1046     {
1047         // Very bad case: If the Fly is bound within another Fly which
1048         // contains columns, the Format should be from that one.
1049         if ( !pFrame->IsLocked() && !pFrame->IsColLocked() &&
1050              pFrame->Lower() && pFrame->Lower()->IsColumnFrame() )
1051             pFrame->InvalidateSize();
1052     }
1053 
1054     // #i85216#
1055     // if vertical position is oriented at a layout frame inside a ghost section,
1056     // assure that the position is invalidated and that the information about
1057     // the vertical position oriented frame is cleared
1058     if ( GetVertPosOrientFrame() && GetVertPosOrientFrame()->IsLayoutFrame() )
1059     {
1060         const SwSectionFrame* pSectFrame( GetVertPosOrientFrame()->FindSctFrame() );
1061         if ( pSectFrame && pSectFrame->GetSection() == nullptr )
1062         {
1063             InvalidatePos();
1064             ClearVertPosOrientFrame();
1065         }
1066     }
1067 }
1068 
1069 /** Change the relative position
1070  *
1071  * The position will be Fix automatically and the attribute is changed accordingly.
1072  */
ChgRelPos(const Point & rNewPos)1073 void SwFlyFrame::ChgRelPos( const Point &rNewPos )
1074 {
1075     if ( GetCurrRelPos() == rNewPos )
1076         return;
1077 
1078     SwFrameFormat *pFormat = GetFormat();
1079     const bool bVert = GetAnchorFrame()->IsVertical();
1080     const SwTwips nNewY = bVert ? rNewPos.X() : rNewPos.Y();
1081     SwTwips nTmpY = nNewY == LONG_MAX ? 0 : nNewY;
1082     if( bVert )
1083         nTmpY = -nTmpY;
1084     SfxItemSet aSet( pFormat->GetDoc()->GetAttrPool(),
1085                      svl::Items<RES_VERT_ORIENT, RES_HORI_ORIENT>{});
1086 
1087     SwFormatVertOrient aVert( pFormat->GetVertOrient() );
1088     const SwTextFrame *pAutoFrame = nullptr;
1089     // #i34948# - handle also at-page and at-fly anchored
1090     // Writer fly frames
1091     const RndStdIds eAnchorType = GetFrameFormat().GetAnchor().GetAnchorId();
1092     if ( eAnchorType == RndStdIds::FLY_AT_PAGE )
1093     {
1094         aVert.SetVertOrient( text::VertOrientation::NONE );
1095         aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
1096     }
1097     else if ( eAnchorType == RndStdIds::FLY_AT_FLY )
1098     {
1099         aVert.SetVertOrient( text::VertOrientation::NONE );
1100         aVert.SetRelationOrient( text::RelOrientation::FRAME );
1101     }
1102     else if ( IsFlyAtContentFrame() || text::VertOrientation::NONE != aVert.GetVertOrient() )
1103     {
1104         if( text::RelOrientation::CHAR == aVert.GetRelationOrient() && IsAutoPos() )
1105         {
1106             if( LONG_MAX != nNewY )
1107             {
1108                 aVert.SetVertOrient( text::VertOrientation::NONE );
1109                 assert(GetAnchorFrame()->IsTextFrame());
1110                 pAutoFrame = static_cast<const SwTextFrame*>(GetAnchorFrame());
1111                 TextFrameIndex const nOfs(pAutoFrame->MapModelToViewPos(
1112                             *pFormat->GetAnchor().GetContentAnchor()));
1113                 while( pAutoFrame->GetFollow() &&
1114                        pAutoFrame->GetFollow()->GetOfst() <= nOfs )
1115                 {
1116                     if( pAutoFrame == GetAnchorFrame() )
1117                         nTmpY += pAutoFrame->GetRelPos().Y();
1118                     nTmpY -= pAutoFrame->GetUpper()->getFramePrintArea().Height();
1119                     pAutoFrame = pAutoFrame->GetFollow();
1120                 }
1121                 nTmpY = static_cast<SwFlyAtContentFrame*>(this)->GetRelCharY(pAutoFrame)-nTmpY;
1122             }
1123             else
1124                 aVert.SetVertOrient( text::VertOrientation::CHAR_BOTTOM );
1125         }
1126         else
1127         {
1128             aVert.SetVertOrient( text::VertOrientation::NONE );
1129             aVert.SetRelationOrient( text::RelOrientation::FRAME );
1130         }
1131     }
1132     aVert.SetPos( nTmpY );
1133     aSet.Put( aVert );
1134 
1135     // For Flys in the Cnt, the horizontal orientation is of no interest,
1136     // as it's always 0
1137     if ( !IsFlyInContentFrame() )
1138     {
1139         const SwTwips nNewX = bVert ? rNewPos.Y() : rNewPos.X();
1140         SwTwips nTmpX = nNewX == LONG_MAX ? 0 : nNewX;
1141         SwFormatHoriOrient aHori( pFormat->GetHoriOrient() );
1142         // #i34948# - handle also at-page and at-fly anchored
1143         // Writer fly frames
1144         if ( eAnchorType == RndStdIds::FLY_AT_PAGE )
1145         {
1146             aHori.SetHoriOrient( text::HoriOrientation::NONE );
1147             aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
1148             aHori.SetPosToggle( false );
1149         }
1150         else if ( eAnchorType == RndStdIds::FLY_AT_FLY )
1151         {
1152             aHori.SetHoriOrient( text::HoriOrientation::NONE );
1153             aHori.SetRelationOrient( text::RelOrientation::FRAME );
1154             aHori.SetPosToggle( false );
1155         }
1156         else if ( IsFlyAtContentFrame() || text::HoriOrientation::NONE != aHori.GetHoriOrient() )
1157         {
1158             aHori.SetHoriOrient( text::HoriOrientation::NONE );
1159             if( text::RelOrientation::CHAR == aHori.GetRelationOrient() && IsAutoPos() )
1160             {
1161                 if( LONG_MAX != nNewX )
1162                 {
1163                     if( !pAutoFrame )
1164                     {
1165                         assert(GetAnchorFrame()->IsTextFrame());
1166                         pAutoFrame = static_cast<const SwTextFrame*>(GetAnchorFrame());
1167                         TextFrameIndex const nOfs(pAutoFrame->MapModelToViewPos(
1168                                     *pFormat->GetAnchor().GetContentAnchor()));
1169                         while( pAutoFrame->GetFollow() &&
1170                                pAutoFrame->GetFollow()->GetOfst() <= nOfs )
1171                             pAutoFrame = pAutoFrame->GetFollow();
1172                     }
1173                     nTmpX -= static_cast<SwFlyAtContentFrame*>(this)->GetRelCharX(pAutoFrame);
1174                 }
1175             }
1176             else
1177                 aHori.SetRelationOrient( text::RelOrientation::FRAME );
1178             aHori.SetPosToggle( false );
1179         }
1180         aHori.SetPos( nTmpX );
1181         aSet.Put( aHori );
1182     }
1183     SetCurrRelPos( rNewPos );
1184     pFormat->GetDoc()->SetAttr( aSet, *pFormat );
1185 
1186 }
1187 
1188 /** "Formats" the Frame; Frame and PrtArea.
1189  *
1190  * The FixSize is not inserted here.
1191  */
Format(vcl::RenderContext *,const SwBorderAttrs * pAttrs)1192 void SwFlyFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderAttrs *pAttrs )
1193 {
1194     OSL_ENSURE( pAttrs, "FlyFrame::Format, pAttrs is 0." );
1195 
1196     ColLock();
1197 
1198     if ( !isFrameAreaSizeValid() )
1199     {
1200         if ( getFrameArea().Top() == FAR_AWAY && getFrameArea().Left() == FAR_AWAY )
1201         {
1202             // Remove safety switch (see SwFrame::CTor)
1203             {
1204                 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1205                 aFrm.Pos().setX(0);
1206                 aFrm.Pos().setY(0);
1207             }
1208 
1209             // #i68520#
1210             InvalidateObjRectWithSpaces();
1211         }
1212 
1213         // Check column width and set it if needed
1214         if ( Lower() && Lower()->IsColumnFrame() )
1215             AdjustColumns( nullptr, false );
1216 
1217         setFrameAreaSizeValid(true);
1218 
1219         const SwTwips nUL = pAttrs->CalcTopLine()  + pAttrs->CalcBottomLine();
1220         const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine();
1221         const SwFormatFrameSize &rFrameSz = GetFormat()->GetFrameSize();
1222         Size aRelSize( CalcRel( rFrameSz ) );
1223 
1224         OSL_ENSURE( pAttrs->GetSize().Height() != 0 || rFrameSz.GetHeightPercent(), "FrameAttr height is 0." );
1225         OSL_ENSURE( pAttrs->GetSize().Width()  != 0 || rFrameSz.GetWidthPercent(), "FrameAttr width is 0." );
1226 
1227         SwRectFnSet aRectFnSet(this);
1228         if( !HasFixSize() )
1229         {
1230             long nMinHeight = 0;
1231             if( IsMinHeight() )
1232                 nMinHeight = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
1233 
1234             SwTwips nRemaining = CalcContentHeight(pAttrs, nMinHeight, nUL);
1235             if( IsMinHeight() && (nRemaining + nUL) < nMinHeight )
1236                 nRemaining = nMinHeight - nUL;
1237             // Because the Grow/Shrink of the Flys does not directly
1238             // set the size - only indirectly by triggering a Format()
1239             // via Invalidate() - the sizes need to be set here.
1240             // Notification is running along already.
1241             // As we already got a lot of zeros per attribute, we block them
1242             // from now on.
1243 
1244             if ( nRemaining < MINFLY )
1245                 nRemaining = MINFLY;
1246 
1247             {
1248                 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1249                 aRectFnSet.SetHeight( aPrt, nRemaining );
1250             }
1251 
1252             nRemaining -= aRectFnSet.GetHeight(getFrameArea());
1253 
1254             {
1255                 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1256                 aRectFnSet.AddBottom( aFrm, nRemaining + nUL );
1257             }
1258 
1259             // #i68520#
1260             if ( nRemaining + nUL != 0 )
1261             {
1262                 InvalidateObjRectWithSpaces();
1263             }
1264 
1265             setFrameAreaSizeValid(true);
1266 
1267             if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT))
1268             {
1269                 // This fly is a textbox of a draw shape.
1270                 SdrObject* pShape = pShapeFormat->FindSdrObject();
1271                 if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pShape) )
1272                 {
1273                     // The shape is a customshape: then inform it about the calculated fly size.
1274                     Size aSize(getFrameArea().Width(), getFrameArea().Height());
1275                     pCustomShape->SuggestTextFrameSize(aSize);
1276                     // Do the calculations normally done after touching editeng text of the shape.
1277                     pCustomShape->NbcSetOutlinerParaObjectForText(nullptr, nullptr);
1278                 }
1279             }
1280         }
1281         else
1282         {
1283             // Fixed Frames do not Format itself
1284             setFrameAreaSizeValid(true);
1285 
1286             // Flys set their size using the attr
1287             SwTwips nNewSize = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
1288             nNewSize -= nUL;
1289             if( nNewSize < MINFLY )
1290                 nNewSize = MINFLY;
1291 
1292             {
1293                 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1294                 aRectFnSet.SetHeight( aPrt, nNewSize );
1295             }
1296 
1297             nNewSize += nUL - aRectFnSet.GetHeight(getFrameArea());
1298 
1299             {
1300                 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1301                 aRectFnSet.AddBottom( aFrm, nNewSize );
1302             }
1303 
1304             // #i68520#
1305             if ( nNewSize != 0 )
1306             {
1307                 InvalidateObjRectWithSpaces();
1308             }
1309         }
1310 
1311         if ( !m_bFormatHeightOnly )
1312         {
1313             OSL_ENSURE( aRelSize == CalcRel( rFrameSz ), "SwFlyFrame::Format CalcRel problem" );
1314             SwTwips nNewSize = aRectFnSet.IsVert() ? aRelSize.Height() : aRelSize.Width();
1315 
1316             if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1317             {
1318                 // #i9046# Autowidth for fly frames
1319                 const SwTwips nAutoWidth = lcl_CalcAutoWidth( *this );
1320                 if ( nAutoWidth )
1321                 {
1322                     if( ATT_MIN_SIZE == rFrameSz.GetWidthSizeType() )
1323                         nNewSize = std::max( nNewSize - nLR, nAutoWidth );
1324                     else
1325                         nNewSize = nAutoWidth;
1326                 }
1327             }
1328             else
1329                 nNewSize -= nLR;
1330 
1331             if( nNewSize < MINFLY )
1332                 nNewSize = MINFLY;
1333 
1334             {
1335                 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1336                 aRectFnSet.SetWidth( aPrt, nNewSize );
1337             }
1338 
1339             nNewSize += nLR - aRectFnSet.GetWidth(getFrameArea());
1340 
1341             {
1342                 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1343                 aRectFnSet.AddRight( aFrm, nNewSize );
1344             }
1345 
1346             // #i68520#
1347             if ( nNewSize != 0 )
1348             {
1349                 InvalidateObjRectWithSpaces();
1350             }
1351         }
1352     }
1353     ColUnlock();
1354 }
1355 
1356 // OD 14.03.2003 #i11760# - change parameter <bNoColl>: type <bool>;
1357 //                          default value = false.
1358 // OD 14.03.2003 #i11760# - add new parameter <bNoCalcFollow> with
1359 //                          default value = false.
1360 // OD 11.04.2003 #108824# - new parameter <bNoCalcFollow> was used by method
1361 //                          <FormatWidthCols(..)> to avoid follow formatting
1362 //                          for text frames. But, unformatted follows causes
1363 //                          problems in method <SwContentFrame::WouldFit_(..)>,
1364 //                          which assumes that the follows are formatted.
1365 //                          Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
CalcContent(SwLayoutFrame * pLay,bool bNoColl)1366 void CalcContent( SwLayoutFrame *pLay, bool bNoColl )
1367 {
1368     vcl::RenderContext* pRenderContext = pLay->getRootFrame()->GetCurrShell()->GetOut();
1369     SwSectionFrame* pSect;
1370     bool bCollect = false;
1371     if( pLay->IsSctFrame() )
1372     {
1373         pSect = static_cast<SwSectionFrame*>(pLay);
1374         if( pSect->IsEndnAtEnd() && !bNoColl )
1375         {
1376             bCollect = true;
1377             SwLayouter::CollectEndnotes( pLay->GetFormat()->GetDoc(), pSect );
1378         }
1379         pSect->CalcFootnoteContent();
1380     }
1381     else
1382         pSect = nullptr;
1383     SwFrame *pFrame = pLay->ContainsAny();
1384     if ( !pFrame )
1385     {
1386         if( pSect )
1387         {
1388             if( pSect->HasFollow() )
1389                 pFrame = pSect->GetFollow()->ContainsAny();
1390             if( !pFrame )
1391             {
1392                 if( pSect->IsEndnAtEnd() )
1393                 {
1394                     if( bCollect )
1395                         pLay->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->
1396                             InsertEndnotes( pSect );
1397                     bool bLock = pSect->IsFootnoteLock();
1398                     pSect->SetFootnoteLock( true );
1399                     pSect->CalcFootnoteContent();
1400                     pSect->CalcFootnoteContent();
1401                     pSect->SetFootnoteLock( bLock );
1402                 }
1403                 return;
1404             }
1405             pFrame->InvalidatePos_();
1406         }
1407         else
1408             return;
1409     }
1410     pFrame->InvalidatePage();
1411 
1412     do
1413     {
1414         // local variables to avoid loops caused by anchored object positioning
1415         SwAnchoredObject* pAgainObj1 = nullptr;
1416         SwAnchoredObject* pAgainObj2 = nullptr;
1417 
1418         // FME 2007-08-30 #i81146# new loop control
1419         int nLoopControlRuns = 0;
1420         const int nLoopControlMax = 20;
1421         const SwFrame* pLoopControlCond = nullptr;
1422 
1423         SwFrame* pLast;
1424         do
1425         {
1426             pLast = pFrame;
1427             if( pFrame->IsVertical() ?
1428                 ( pFrame->GetUpper()->getFramePrintArea().Height() != pFrame->getFrameArea().Height() )
1429                 : ( pFrame->GetUpper()->getFramePrintArea().Width() != pFrame->getFrameArea().Width() ) )
1430             {
1431                 pFrame->Prepare( PREP_FIXSIZE_CHG );
1432                 pFrame->InvalidateSize_();
1433             }
1434 
1435             if ( pFrame->IsTabFrame() )
1436             {
1437                 static_cast<SwTabFrame*>(pFrame)->m_bCalcLowers = true;
1438                 // OD 26.08.2003 #i18103# - lock move backward of follow table,
1439                 // if no section content is formatted or follow table belongs
1440                 // to the section, which content is formatted.
1441                 if ( static_cast<SwTabFrame*>(pFrame)->IsFollow() &&
1442                      ( !pSect || pSect == pFrame->FindSctFrame() ) )
1443                 {
1444                     static_cast<SwTabFrame*>(pFrame)->m_bLockBackMove = true;
1445                 }
1446             }
1447 
1448             {
1449                 SwFrameDeleteGuard aDeletePageGuard(pSect ? pSect->FindPageFrame() : nullptr);
1450                 SwFrameDeleteGuard aDeleteGuard(pSect);
1451                 pFrame->Calc(pRenderContext);
1452             }
1453 
1454             // OD 14.03.2003 #i11760# - reset control flag for follow format.
1455             if ( pFrame->IsTextFrame() )
1456             {
1457                 static_cast<SwTextFrame*>(pFrame)->AllowFollowFormat();
1458             }
1459 
1460             // #111937# The keep-attribute can cause the position
1461             // of the prev to be invalid:
1462             // OD 2004-03-15 #116560# - Do not consider invalid previous frame
1463             // due to its keep-attribute, if current frame is a follow or is locked.
1464             // #i44049# - do not consider invalid previous
1465             // frame due to its keep-attribute, if it can't move forward.
1466             // #i57765# - do not consider invalid previous
1467             // frame, if current frame has a column/page break before attribute.
1468             SwFrame* pTmpPrev = pFrame->FindPrev();
1469             SwFlowFrame* pTmpPrevFlowFrame = pTmpPrev && pTmpPrev->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev) : nullptr;
1470             SwFlowFrame* pTmpFlowFrame     = pFrame->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pFrame) : nullptr;
1471 
1472             bool bPrevInvalid = pTmpPrevFlowFrame && pTmpFlowFrame &&
1473                                !pTmpFlowFrame->IsFollow() &&
1474                                !StackHack::IsLocked() && // #i76382#
1475                                !pTmpFlowFrame->IsJoinLocked() &&
1476                                !pTmpPrev->isFrameAreaPositionValid() &&
1477                                 pLay->IsAnLower( pTmpPrev ) &&
1478                                 pTmpPrevFlowFrame->IsKeep(pTmpPrev->GetAttrSet()->GetKeep(), pTmpPrev->GetBreakItem()) &&
1479                                 pTmpPrevFlowFrame->IsKeepFwdMoveAllowed();
1480 
1481             // format floating screen objects anchored to the frame.
1482             if ( !bPrevInvalid && pFrame->GetDrawObjs() && pLay->IsAnLower( pFrame ) )
1483             {
1484                 bool bAgain = false;
1485                 bool bRestartLayoutProcess = false;
1486                 SwPageFrame* pPageFrame = pFrame->FindPageFrame();
1487                 size_t nCnt = pFrame->GetDrawObjs()->size();
1488                 size_t i = 0;
1489                 while ( i < nCnt )
1490                 {
1491                     // #i28701#
1492                     SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[i];
1493                     assert(pAnchoredObj);
1494 
1495                     // determine if anchored object has to be
1496                     // formatted and, in case, format it
1497                     if ( !pAnchoredObj->PositionLocked() && pAnchoredObj->IsFormatPossible() )
1498                     {
1499                         // #i43737# - no invalidation of
1500                         // anchored object needed - causes loops for as-character
1501                         // anchored objects.
1502                         //pAnchoredObj->InvalidateObjPos();
1503                         SwRect aRect( pAnchoredObj->GetObjRect() );
1504                         if ( !SwObjectFormatter::FormatObj( *pAnchoredObj, pFrame, pPageFrame ) )
1505                         {
1506                             bRestartLayoutProcess = true;
1507                             break;
1508                         }
1509                         // #i3317# - restart layout process,
1510                         // if the position of the anchored object is locked now.
1511                         if ( pAnchoredObj->PositionLocked() )
1512                         {
1513                             bRestartLayoutProcess = true;
1514                             break;
1515                         }
1516 
1517                         if ( aRect != pAnchoredObj->GetObjRect() )
1518                         {
1519                             bAgain = true;
1520                             if ( pAgainObj2 == pAnchoredObj )
1521                             {
1522                                 OSL_FAIL( "::CalcContent(..) - loop detected, perform attribute changes to avoid the loop" );
1523                                 // Prevent oscillation
1524                                 SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
1525                                 SwFormatSurround aAttr( rFormat.GetSurround() );
1526                                 if( css::text::WrapTextMode_THROUGH != aAttr.GetSurround() )
1527                                 {
1528                                     // When on auto position, we can only set it to
1529                                     // flow through
1530                                     if ((rFormat.GetAnchor().GetAnchorId() ==
1531                                             RndStdIds::FLY_AT_CHAR) &&
1532                                         (css::text::WrapTextMode_PARALLEL ==
1533                                             aAttr.GetSurround()))
1534                                     {
1535                                         aAttr.SetSurround( css::text::WrapTextMode_THROUGH );
1536                                     }
1537                                     else
1538                                     {
1539                                         aAttr.SetSurround( css::text::WrapTextMode_PARALLEL );
1540                                     }
1541                                     rFormat.LockModify();
1542                                     rFormat.SetFormatAttr( aAttr );
1543                                     rFormat.UnlockModify();
1544                                 }
1545                             }
1546                             else
1547                             {
1548                                 if ( pAgainObj1 == pAnchoredObj )
1549                                     pAgainObj2 = pAnchoredObj;
1550                                 pAgainObj1 = pAnchoredObj;
1551                             }
1552                         }
1553 
1554                         if ( !pFrame->GetDrawObjs() )
1555                             break;
1556                         if ( pFrame->GetDrawObjs()->size() < nCnt )
1557                         {
1558                             --nCnt;
1559                             // Do not increment index, in this case
1560                             continue;
1561                         }
1562                     }
1563                     ++i;
1564                 }
1565 
1566                 // #i28701# - restart layout process, if
1567                 // requested by floating screen object formatting
1568                 if ( bRestartLayoutProcess )
1569                 {
1570                     pFrame = pLay->ContainsAny();
1571                     pAgainObj1 = nullptr;
1572                     pAgainObj2 = nullptr;
1573                     continue;
1574                 }
1575 
1576                 // OD 2004-05-17 #i28701# - format anchor frame after its objects
1577                 // are formatted, if the wrapping style influence has to be considered.
1578                 if ( pLay->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) )
1579                 {
1580                     pFrame->Calc(pRenderContext);
1581                 }
1582 
1583                 if ( bAgain )
1584                 {
1585                     pFrame = pLay->ContainsContent();
1586                     if ( pFrame && pFrame->IsInTab() )
1587                         pFrame = pFrame->FindTabFrame();
1588                     if( pFrame && pFrame->IsInSct() )
1589                     {
1590                         SwSectionFrame* pTmp = pFrame->FindSctFrame();
1591                         if( pTmp != pLay && pLay->IsAnLower( pTmp ) )
1592                             pFrame = pTmp;
1593                     }
1594 
1595                     if ( pFrame == pLoopControlCond )
1596                         ++nLoopControlRuns;
1597                     else
1598                     {
1599                         nLoopControlRuns = 0;
1600                         pLoopControlCond = pFrame;
1601                     }
1602 
1603                     if ( nLoopControlRuns < nLoopControlMax )
1604                         continue;
1605 
1606                     OSL_FAIL( "LoopControl in CalcContent" );
1607                 }
1608             }
1609             if ( pFrame->IsTabFrame() )
1610             {
1611                 if ( static_cast<SwTabFrame*>(pFrame)->IsFollow() )
1612                     static_cast<SwTabFrame*>(pFrame)->m_bLockBackMove = false;
1613             }
1614 
1615             pFrame = bPrevInvalid ? pTmpPrev : pFrame->FindNext();
1616             if( !bPrevInvalid && pFrame && pFrame->IsSctFrame() && pSect )
1617             {
1618                 // Empty SectionFrames could be present here
1619                 while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() )
1620                     pFrame = pFrame->FindNext();
1621 
1622                 // If FindNext returns the Follow of the original Area, we want to
1623                 // continue with this content as long as it flows back.
1624                 if( pFrame && pFrame->IsSctFrame() && ( pFrame == pSect->GetFollow() ||
1625                     static_cast<SwSectionFrame*>(pFrame)->IsAnFollow( pSect ) ) )
1626                 {
1627                     pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1628                     if( pFrame )
1629                         pFrame->InvalidatePos_();
1630                 }
1631             }
1632           // Stay in the pLay
1633           // Except for SectionFrames with Follow: the first ContentFrame of the Follow
1634           // will be formatted, so that it gets a chance to load in the pLay.
1635           // As long as these Frames are loading in pLay, we continue
1636         } while ( pFrame &&
1637                   ( pLay->IsAnLower( pFrame ) ||
1638                     ( pSect &&
1639                       ( ( pSect->HasFollow() &&
1640                           ( pLay->IsAnLower( pLast ) ||
1641                             ( pLast->IsInSct() &&
1642                               pLast->FindSctFrame()->IsAnFollow(pSect) ) ) &&
1643                           pSect->GetFollow()->IsAnLower( pFrame )  ) ||
1644                         ( pFrame->IsInSct() &&
1645                           pFrame->FindSctFrame()->IsAnFollow( pSect ) ) ) ) ) );
1646         if( pSect )
1647         {
1648             if( bCollect )
1649             {
1650                 pLay->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->InsertEndnotes(pSect);
1651                 pSect->CalcFootnoteContent();
1652             }
1653             if( pSect->HasFollow() )
1654             {
1655                 SwSectionFrame* pNxt = pSect->GetFollow();
1656                 while( pNxt && !pNxt->ContainsContent() )
1657                     pNxt = pNxt->GetFollow();
1658                 if( pNxt )
1659                     pNxt->CalcFootnoteContent();
1660             }
1661             if( bCollect )
1662             {
1663                 pFrame = pLay->ContainsAny();
1664                 bCollect = false;
1665                 if( pFrame )
1666                     continue;
1667             }
1668         }
1669         break;
1670     }
1671     while( true );
1672 }
1673 
1674 // OD 2004-03-23 #i26791#
MakeObjPos()1675 void SwFlyFrame::MakeObjPos()
1676 {
1677     if ( !isFrameAreaPositionValid() )
1678     {
1679         vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
1680         setFrameAreaPositionValid(true);
1681 
1682         // OD 29.10.2003 #113049# - use new class to position object
1683         GetAnchorFrame()->Calc(pRenderContext);
1684         objectpositioning::SwToLayoutAnchoredObjectPosition
1685                 aObjPositioning( *GetVirtDrawObj() );
1686         aObjPositioning.CalcPosition();
1687 
1688         // #i58280#
1689         // update relative position
1690         SetCurrRelPos( aObjPositioning.GetRelPos() );
1691 
1692         {
1693             SwRectFnSet aRectFnSet(GetAnchorFrame());
1694             SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1695             aFrm.Pos( aObjPositioning.GetRelPos() );
1696             aFrm.Pos() += aRectFnSet.GetPos(GetAnchorFrame()->getFrameArea());
1697         }
1698 
1699         // #i69335#
1700         InvalidateObjRectWithSpaces();
1701     }
1702 }
1703 
MakePrtArea(const SwBorderAttrs & rAttrs)1704 void SwFlyFrame::MakePrtArea( const SwBorderAttrs &rAttrs )
1705 {
1706     if ( !isFramePrintAreaValid() )
1707     {
1708         setFramePrintAreaValid(true);
1709 
1710         // OD 31.07.2003 #110978# - consider vertical layout
1711         SwRectFnSet aRectFnSet(this);
1712         aRectFnSet.SetXMargins( *this, rAttrs.CalcLeftLine(),
1713                                         rAttrs.CalcRightLine() );
1714         aRectFnSet.SetYMargins( *this, rAttrs.CalcTopLine(),
1715                                         rAttrs.CalcBottomLine() );
1716     }
1717 }
1718 
MakeContentPos(const SwBorderAttrs & rAttrs)1719 void SwFlyFrame::MakeContentPos( const SwBorderAttrs &rAttrs )
1720 {
1721     if ( m_bValidContentPos )
1722         return;
1723 
1724     m_bValidContentPos = true;
1725 
1726     const SwTwips nUL = rAttrs.CalcTopLine()  + rAttrs.CalcBottomLine();
1727     Size aRelSize( CalcRel( GetFormat()->GetFrameSize() ) );
1728 
1729     SwRectFnSet aRectFnSet(this);
1730     long nMinHeight = 0;
1731     if( IsMinHeight() )
1732         nMinHeight = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
1733 
1734     Point aNewContentPos = getFramePrintArea().Pos();
1735     const SdrTextVertAdjust nAdjust = GetFormat()->GetTextVertAdjust().GetValue();
1736 
1737     if( nAdjust != SDRTEXTVERTADJUST_TOP )
1738     {
1739         const SwTwips nContentHeight = CalcContentHeight(&rAttrs, nMinHeight, nUL);
1740         SwTwips nDiff = 0;
1741 
1742         if( nContentHeight != 0)
1743             nDiff = aRectFnSet.GetHeight(getFramePrintArea()) - nContentHeight;
1744 
1745         if( nDiff > 0 )
1746         {
1747             if( nAdjust == SDRTEXTVERTADJUST_CENTER )
1748             {
1749                 if( aRectFnSet.IsVertL2R() )
1750                     aNewContentPos.setX(aNewContentPos.getX() + nDiff/2);
1751                 else if( aRectFnSet.IsVert() )
1752                     aNewContentPos.setX(aNewContentPos.getX() - nDiff/2);
1753                 else
1754                     aNewContentPos.setY(aNewContentPos.getY() + nDiff/2);
1755             }
1756             else if( nAdjust == SDRTEXTVERTADJUST_BOTTOM )
1757             {
1758                 if( aRectFnSet.IsVertL2R() )
1759                     aNewContentPos.setX(aNewContentPos.getX() + nDiff);
1760                 else if( aRectFnSet.IsVert() )
1761                     aNewContentPos.setX(aNewContentPos.getX() - nDiff);
1762                 else
1763                     aNewContentPos.setY(aNewContentPos.getY() + nDiff);
1764             }
1765         }
1766     }
1767     if( aNewContentPos != ContentPos() )
1768     {
1769         ContentPos() = aNewContentPos;
1770         for( SwFrame *pFrame = Lower(); pFrame; pFrame = pFrame->GetNext())
1771         {
1772             pFrame->InvalidatePos();
1773         }
1774     }
1775 
1776 }
1777 
InvalidateContentPos()1778 void SwFlyFrame::InvalidateContentPos()
1779 {
1780     m_bValidContentPos = false;
1781     Invalidate_();
1782 }
1783 
SelectionHasChanged(SwFEShell * pShell)1784 void SwFlyFrame::SelectionHasChanged(SwFEShell* pShell)
1785 {
1786     SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >(pShell);
1787     if (pWrtSh == nullptr)
1788         return;
1789 
1790     UpdateUnfloatButton(pWrtSh, IsShowUnfloatButton(pWrtSh));
1791 }
1792 
IsShowUnfloatButton(SwWrtShell * pWrtSh) const1793 bool SwFlyFrame::IsShowUnfloatButton(SwWrtShell* pWrtSh) const
1794 {
1795     if (pWrtSh == nullptr)
1796         return false;
1797 
1798     // In read only mode we don't allow unfloat operation
1799     if (pWrtSh->GetViewOptions()->IsReadonly())
1800         return false;
1801 
1802     const SdrObject *pObj = GetFrameFormat().FindRealSdrObject();
1803     if (pObj == nullptr)
1804         return false;
1805 
1806     // SwFlyFrame itself can mean images, ole objects, etc, but we interested in actual text frames
1807     if (SwFEShell::GetObjCntType(*pObj) != OBJCNT_FLY)
1808         return false;
1809 
1810     // We show the button only for the selected text frame
1811     SwDrawView *pView = pWrtSh->Imp()->GetDrawView();
1812     if (pView == nullptr)
1813         return false;
1814 
1815     // Fly frame can be selected only alone
1816     if (pView->GetMarkedObjectList().GetMarkCount() != 1)
1817         return false;
1818 
1819     if(!pView->IsObjMarked(pObj))
1820         return false;
1821 
1822     // A frame is a floating table if there is only one table (and maybe some whitespaces) inside it
1823     int nTableCount = 0;
1824     const SwFrame* pLower = GetLower();
1825     const SwTabFrame* pTable = nullptr;
1826     while (pLower)
1827     {
1828         if (pLower->IsTabFrame())
1829         {
1830             pTable = static_cast<const SwTabFrame*>(pLower);
1831             ++nTableCount;
1832             if (nTableCount > 1 || pTable == nullptr)
1833                 return false;
1834         }
1835 
1836         if (pLower->IsTextFrame())
1837         {
1838             const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(pLower);
1839             if (!pTextFrame->GetText().trim().isEmpty())
1840                 return false;
1841         }
1842         pLower = pLower->GetNext();
1843     }
1844 
1845     if (nTableCount != 1 || pTable == nullptr)
1846         return false;
1847 
1848     // Show the unfold button only for multipage tables
1849     const SwBodyFrame *pBody = GetAnchorFrame()->FindBodyFrame();
1850     if (pBody == nullptr)
1851         return false;
1852 
1853     long nBodyHeight = pBody->getFrameArea().Height();
1854     long nTableHeight = pTable->getFrameArea().Height();
1855     long nFrameOffset = std::abs(GetAnchorFrame()->getFrameArea().Top() - pBody->getFrameArea().Top());
1856 
1857     return nBodyHeight < nTableHeight + nFrameOffset;
1858 }
1859 
ActiveUnfloatButton(SwWrtShell * pWrtSh)1860 void SwFlyFrame::ActiveUnfloatButton(SwWrtShell* pWrtSh)
1861 {
1862     SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
1863     SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager();
1864     SwFrameControlPtr pControl = rMngr.GetControl(FloatingTable, this);
1865     if (pControl.get() || pControl->GetWindow())
1866     {
1867         pControl->GetWindow()->MouseButtonDown(MouseEvent());
1868     }
1869 }
1870 
UpdateUnfloatButton(SwWrtShell * pWrtSh,bool bShow) const1871 void SwFlyFrame::UpdateUnfloatButton(SwWrtShell* pWrtSh, bool bShow) const
1872 {
1873     if (pWrtSh == nullptr)
1874         return;
1875 
1876     SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
1877     SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager();
1878     Point aTopRightPixel = rEditWin.LogicToPixel( getFrameArea().TopRight() );
1879     rMngr.SetUnfloatTableButton(this, bShow,  aTopRightPixel);
1880 }
1881 
Grow_(SwTwips nDist,bool bTst)1882 SwTwips SwFlyFrame::Grow_( SwTwips nDist, bool bTst )
1883 {
1884     SwRectFnSet aRectFnSet(this);
1885     if ( Lower() && !IsColLocked() && !HasFixSize() )
1886     {
1887         SwTwips nSize = aRectFnSet.GetHeight(getFrameArea());
1888         if( nSize > 0 && nDist > ( LONG_MAX - nSize ) )
1889             nDist = LONG_MAX - nSize;
1890 
1891         if ( nDist <= 0 )
1892             return 0;
1893 
1894         if ( Lower()->IsColumnFrame() )
1895         {   // If it's a Column Frame, the Format takes control of the
1896             // resizing (due to the adjustment).
1897             if ( !bTst )
1898             {
1899                 // #i28701# - unlock position of Writer fly frame
1900                 UnlockPosition();
1901                 InvalidatePos_();
1902                 InvalidateSize();
1903             }
1904             return 0;
1905         }
1906 
1907         if ( !bTst )
1908         {
1909             const SwRect aOld( GetObjRectWithSpaces() );
1910             InvalidateSize_();
1911             const bool bOldLock = m_bLocked;
1912             Unlock();
1913             if ( IsFlyFreeFrame() )
1914             {
1915                 // #i37068# - no format of position here
1916                 // and prevent move in method <CheckClip(..)>.
1917                 // This is needed to prevent layout loop caused by nested
1918                 // Writer fly frames - inner Writer fly frames format its
1919                 // anchor, which grows/shrinks the outer Writer fly frame.
1920                 // Note: position will be invalidated below.
1921                 setFrameAreaPositionValid(true);
1922 
1923                 // #i55416#
1924                 // Suppress format of width for autowidth frame, because the
1925                 // format of the width would call <SwTextFrame::CalcFitToContent()>
1926                 // for the lower frame, which initiated this grow.
1927                 const bool bOldFormatHeightOnly = m_bFormatHeightOnly;
1928                 const SwFormatFrameSize& rFrameSz = GetFormat()->GetFrameSize();
1929                 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1930                 {
1931                     m_bFormatHeightOnly = true;
1932                 }
1933                 SwViewShell* pSh = getRootFrame()->GetCurrShell();
1934                 if (pSh)
1935                 {
1936                     static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( true );
1937                     static_cast<SwFlyFreeFrame*>(this)->SwFlyFreeFrame::MakeAll(pSh->GetOut());
1938                     static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( false );
1939                 }
1940                 // #i55416#
1941                 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
1942                 {
1943                     m_bFormatHeightOnly = bOldFormatHeightOnly;
1944                 }
1945             }
1946             else
1947                 MakeAll(getRootFrame()->GetCurrShell()->GetOut());
1948             InvalidateSize_();
1949             InvalidatePos();
1950             if ( bOldLock )
1951                 Lock();
1952             const SwRect aNew( GetObjRectWithSpaces() );
1953             if ( aOld != aNew )
1954                 ::Notify( this, FindPageFrame(), aOld );
1955             return aRectFnSet.GetHeight(aNew)-aRectFnSet.GetHeight(aOld);
1956         }
1957         return nDist;
1958     }
1959     return 0;
1960 }
1961 
Shrink_(SwTwips nDist,bool bTst)1962 SwTwips SwFlyFrame::Shrink_( SwTwips nDist, bool bTst )
1963 {
1964     if( Lower() && !IsColLocked() && !HasFixSize() )
1965     {
1966         SwRectFnSet aRectFnSet(this);
1967         SwTwips nHeight = aRectFnSet.GetHeight(getFrameArea());
1968         if ( nDist > nHeight )
1969             nDist = nHeight;
1970 
1971         SwTwips nVal = nDist;
1972         if ( IsMinHeight() )
1973         {
1974             const SwFormatFrameSize& rFormatSize = GetFormat()->GetFrameSize();
1975             SwTwips nFormatHeight = aRectFnSet.IsVert() ? rFormatSize.GetWidth() : rFormatSize.GetHeight();
1976 
1977             nVal = std::min( nDist, nHeight - nFormatHeight );
1978         }
1979 
1980         if ( nVal <= 0 )
1981             return 0;
1982 
1983         if ( Lower()->IsColumnFrame() )
1984         {   // If it's a Column Frame, the Format takes control of the
1985             // resizing (due to the adjustment).
1986             if ( !bTst )
1987             {
1988                 SwRect aOld( GetObjRectWithSpaces() );
1989 
1990                 {
1991                     SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1992                     aRectFnSet.SetHeight( aFrm, nHeight - nVal );
1993                 }
1994 
1995                 // #i68520#
1996                 if ( nHeight - nVal != 0 )
1997                 {
1998                     InvalidateObjRectWithSpaces();
1999                 }
2000 
2001                 nHeight = aRectFnSet.GetHeight(getFramePrintArea());
2002 
2003                 {
2004                     SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
2005                     aRectFnSet.SetHeight( aPrt, nHeight - nVal );
2006                 }
2007 
2008                 InvalidatePos_();
2009                 InvalidateSize();
2010                 ::Notify( this, FindPageFrame(), aOld );
2011                 NotifyDrawObj();
2012                 if ( GetAnchorFrame()->IsInFly() )
2013                     AnchorFrame()->FindFlyFrame()->Shrink( nDist, bTst );
2014             }
2015             return 0;
2016         }
2017 
2018         if ( !bTst )
2019         {
2020             const SwRect aOld( GetObjRectWithSpaces() );
2021             InvalidateSize_();
2022             const bool bOldLocked = m_bLocked;
2023             Unlock();
2024             if ( IsFlyFreeFrame() )
2025             {
2026                 // #i37068# - no format of position here
2027                 // and prevent move in method <CheckClip(..)>.
2028                 // This is needed to prevent layout loop caused by nested
2029                 // Writer fly frames - inner Writer fly frames format its
2030                 // anchor, which grows/shrinks the outer Writer fly frame.
2031                 // Note: position will be invalidated below.
2032                 setFrameAreaPositionValid(true);
2033 
2034                 // #i55416#
2035                 // Suppress format of width for autowidth frame, because the
2036                 // format of the width would call <SwTextFrame::CalcFitToContent()>
2037                 // for the lower frame, which initiated this shrink.
2038                 const bool bOldFormatHeightOnly = m_bFormatHeightOnly;
2039                 const SwFormatFrameSize& rFrameSz = GetFormat()->GetFrameSize();
2040                 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
2041                 {
2042                     m_bFormatHeightOnly = true;
2043                 }
2044                 static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( true );
2045                 static_cast<SwFlyFreeFrame*>(this)->SwFlyFreeFrame::MakeAll(getRootFrame()->GetCurrShell()->GetOut());
2046                 static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( false );
2047                 // #i55416#
2048                 if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
2049                 {
2050                     m_bFormatHeightOnly = bOldFormatHeightOnly;
2051                 }
2052             }
2053             else
2054                 MakeAll(getRootFrame()->GetCurrShell()->GetOut());
2055             InvalidateSize_();
2056             InvalidatePos();
2057             if ( bOldLocked )
2058                 Lock();
2059             const SwRect aNew( GetObjRectWithSpaces() );
2060             if ( aOld != aNew )
2061             {
2062                 ::Notify( this, FindPageFrame(), aOld );
2063                 if ( GetAnchorFrame()->IsInFly() )
2064                     AnchorFrame()->FindFlyFrame()->Shrink( nDist, bTst );
2065             }
2066             return aRectFnSet.GetHeight(aOld) -
2067                    aRectFnSet.GetHeight(aNew);
2068         }
2069         return nVal;
2070     }
2071     return 0;
2072 }
2073 
ChgSize(const Size & aNewSize)2074 Size SwFlyFrame::ChgSize( const Size& aNewSize )
2075 {
2076     // #i53298#
2077     // If the fly frame anchored at-paragraph or at-character contains an OLE
2078     // object, assure that the new size fits into the current clipping area
2079     // of the fly frame
2080     Size aAdjustedNewSize( aNewSize );
2081     {
2082         if ( dynamic_cast<SwFlyAtContentFrame*>(this) &&
2083              Lower() && dynamic_cast<SwNoTextFrame*>(Lower()) &&
2084              static_cast<SwNoTextFrame*>(Lower())->GetNode()->GetOLENode() )
2085         {
2086             SwRect aClipRect;
2087             ::CalcClipRect( GetVirtDrawObj(), aClipRect, false );
2088             if ( aAdjustedNewSize.Width() > aClipRect.Width() )
2089             {
2090                 aAdjustedNewSize.setWidth( aClipRect.Width() );
2091             }
2092             if ( aAdjustedNewSize.Height() > aClipRect.Height() )
2093             {
2094                 aAdjustedNewSize.setWidth( aClipRect.Height() );
2095             }
2096         }
2097     }
2098 
2099     if ( aAdjustedNewSize != getFrameArea().SSize() )
2100     {
2101         SwFrameFormat *pFormat = GetFormat();
2102         SwFormatFrameSize aSz( pFormat->GetFrameSize() );
2103         aSz.SetWidth( aAdjustedNewSize.Width() );
2104         aSz.SetHeight( aAdjustedNewSize.Height() );
2105         // go via the Doc for UNDO
2106         pFormat->GetDoc()->SetAttr( aSz, *pFormat );
2107         return aSz.GetSize();
2108     }
2109     else
2110         return getFrameArea().SSize();
2111 }
2112 
IsLowerOf(const SwLayoutFrame * pUpperFrame) const2113 bool SwFlyFrame::IsLowerOf( const SwLayoutFrame* pUpperFrame ) const
2114 {
2115     OSL_ENSURE( GetAnchorFrame(), "8-( Fly is lost in Space." );
2116     const SwFrame* pFrame = GetAnchorFrame();
2117     do
2118     {
2119         if ( pFrame == pUpperFrame )
2120             return true;
2121         pFrame = pFrame->IsFlyFrame()
2122                ? static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame()
2123                : pFrame->GetUpper();
2124     } while ( pFrame );
2125     return false;
2126 }
2127 
Cut()2128 void SwFlyFrame::Cut()
2129 {
2130 }
2131 
AppendFly(SwFlyFrame * pNew)2132 void SwFrame::AppendFly( SwFlyFrame *pNew )
2133 {
2134     if (!m_pDrawObjs)
2135     {
2136         m_pDrawObjs.reset(new SwSortedObjs());
2137     }
2138     m_pDrawObjs->Insert( *pNew );
2139     pNew->ChgAnchorFrame( this );
2140 
2141     // Register at the page
2142     // If there's none present, register via SwPageFrame::PreparePage
2143     SwPageFrame* pPage = FindPageFrame();
2144     if ( pPage != nullptr )
2145     {
2146         pPage->AppendFlyToPage( pNew );
2147     }
2148 }
2149 
RemoveFly(SwFlyFrame * pToRemove)2150 void SwFrame::RemoveFly( SwFlyFrame *pToRemove )
2151 {
2152     // Deregister from the page
2153     // Could already have happened, if the page was already destructed
2154     SwPageFrame *pPage = pToRemove->FindPageFrame();
2155     if ( pPage && pPage->GetSortedObjs() )
2156     {
2157         pPage->RemoveFlyFromPage( pToRemove );
2158     }
2159     // #i73201#
2160     else
2161     {
2162         if ( pToRemove->IsAccessibleFrame() &&
2163              pToRemove->GetFormat() &&
2164              !pToRemove->IsFlyInContentFrame() )
2165         {
2166             SwRootFrame *pRootFrame = getRootFrame();
2167             if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
2168             {
2169                 SwViewShell *pVSh = pRootFrame->GetCurrShell();
2170                 if( pVSh && pVSh->Imp() )
2171                 {
2172                     pVSh->Imp()->DisposeAccessibleFrame( pToRemove );
2173                 }
2174             }
2175         }
2176     }
2177 
2178     m_pDrawObjs->Remove(*pToRemove);
2179     if (!m_pDrawObjs->size())
2180     {
2181         m_pDrawObjs.reset();
2182     }
2183 
2184     pToRemove->ChgAnchorFrame( nullptr );
2185 
2186     if ( !pToRemove->IsFlyInContentFrame() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
2187         GetUpper()->InvalidateSize();
2188 }
2189 
AppendDrawObj(SwAnchoredObject & _rNewObj)2190 void SwFrame::AppendDrawObj( SwAnchoredObject& _rNewObj )
2191 {
2192     assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2193 
2194     if ( dynamic_cast<const SwAnchoredDrawObject*>( &_rNewObj) ==  nullptr )
2195     {
2196         OSL_FAIL( "SwFrame::AppendDrawObj(..) - anchored object of unexpected type -> object not appended" );
2197         return;
2198     }
2199 
2200     if ( dynamic_cast<const SwDrawVirtObj*>(_rNewObj.GetDrawObj()) ==  nullptr &&
2201          _rNewObj.GetAnchorFrame() && _rNewObj.GetAnchorFrame() != this )
2202     {
2203         assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2204         // perform disconnect from layout, if 'master' drawing object is appended
2205         // to a new frame.
2206         static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
2207                                                 DisconnectFromLayout( false );
2208         assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2209     }
2210 
2211     if ( _rNewObj.GetAnchorFrame() != this )
2212     {
2213         if (!m_pDrawObjs)
2214         {
2215             m_pDrawObjs.reset(new SwSortedObjs());
2216         }
2217         m_pDrawObjs->Insert(_rNewObj);
2218         _rNewObj.ChgAnchorFrame( this );
2219     }
2220 
2221     // #i113730#
2222     // Assure the control objects and group objects containing controls are on the control layer
2223     if ( ::CheckControlLayer( _rNewObj.DrawObj() ) )
2224     {
2225         const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
2226         const SdrLayerID aCurrentLayer(_rNewObj.DrawObj()->GetLayer());
2227         const SdrLayerID aControlLayerID(rIDDMA.GetControlsId());
2228         const SdrLayerID aInvisibleControlLayerID(rIDDMA.GetInvisibleControlsId());
2229 
2230         if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
2231         {
2232             if ( aCurrentLayer == rIDDMA.GetInvisibleHellId() ||
2233                  aCurrentLayer == rIDDMA.GetInvisibleHeavenId() )
2234             {
2235                 _rNewObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
2236             }
2237             else
2238             {
2239                 _rNewObj.DrawObj()->SetLayer(aControlLayerID);
2240             }
2241             //The layer is part of the key used to sort the obj, so update
2242             //its position if the layer changed.
2243             m_pDrawObjs->Update(_rNewObj);
2244         }
2245     }
2246 
2247     // no direct positioning needed, but invalidate the drawing object position
2248     _rNewObj.InvalidateObjPos();
2249 
2250     // register at page frame
2251     SwPageFrame* pPage = FindPageFrame();
2252     if ( pPage )
2253     {
2254         pPage->AppendDrawObjToPage( _rNewObj );
2255     }
2256 
2257     // Notify accessible layout.
2258     SwViewShell* pSh = getRootFrame()->GetCurrShell();
2259     if( pSh )
2260     {
2261         SwRootFrame* pLayout = getRootFrame();
2262         if( pLayout && pLayout->IsAnyShellAccessible() )
2263         {
2264             pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
2265         }
2266     }
2267 
2268     assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2269 }
2270 
RemoveDrawObj(SwAnchoredObject & _rToRemoveObj)2271 void SwFrame::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
2272 {
2273     // Notify accessible layout.
2274     SwViewShell* pSh = getRootFrame()->GetCurrShell();
2275     if( pSh )
2276     {
2277         SwRootFrame* pLayout = getRootFrame();
2278         if (pLayout && pLayout->IsAnyShellAccessible())
2279             pSh->Imp()->DisposeAccessibleObj(_rToRemoveObj.GetDrawObj(), false);
2280     }
2281 
2282     // deregister from page frame
2283     SwPageFrame* pPage = _rToRemoveObj.GetPageFrame();
2284     if ( pPage && pPage->GetSortedObjs() )
2285         pPage->RemoveDrawObjFromPage( _rToRemoveObj );
2286 
2287     m_pDrawObjs->Remove(_rToRemoveObj);
2288     if (!m_pDrawObjs->size())
2289     {
2290         m_pDrawObjs.reset();
2291     }
2292     _rToRemoveObj.ChgAnchorFrame( nullptr );
2293 
2294     assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
2295 }
2296 
InvalidateObjs(const bool _bNoInvaOfAsCharAnchoredObjs)2297 void SwFrame::InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs )
2298 {
2299     if ( GetDrawObjs() )
2300     {
2301         // #i26945# - determine page the frame is on,
2302         // in order to check, if anchored object is registered at the same
2303         // page.
2304         const SwPageFrame* pPageFrame = FindPageFrame();
2305         // #i28701# - re-factoring
2306         for (SwAnchoredObject* pAnchoredObj : *GetDrawObjs())
2307         {
2308             if ( _bNoInvaOfAsCharAnchoredObjs &&
2309                  (pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
2310                     == RndStdIds::FLY_AS_CHAR) )
2311             {
2312                 continue;
2313             }
2314             // #i26945# - no invalidation, if anchored object
2315             // isn't registered at the same page and instead is registered at
2316             // the page, where its anchor character text frame is on.
2317             if ( pAnchoredObj->GetPageFrame() &&
2318                  pAnchoredObj->GetPageFrame() != pPageFrame )
2319             {
2320                 SwTextFrame* pAnchorCharFrame = pAnchoredObj->FindAnchorCharFrame();
2321                 if ( pAnchorCharFrame &&
2322                      pAnchoredObj->GetPageFrame() == pAnchorCharFrame->FindPageFrame() )
2323                 {
2324                     continue;
2325                 }
2326                 // #115759# - unlock its position, if anchored
2327                 // object isn't registered at the page, where its anchor
2328                 // character text frame is on, respectively if it has no
2329                 // anchor character text frame.
2330                 else
2331                 {
2332                     pAnchoredObj->UnlockPosition();
2333                 }
2334             }
2335             // #i51474# - reset flag, that anchored object
2336             // has cleared environment, and unlock its position, if the anchored
2337             // object is registered at the same page as the anchor frame is on.
2338             if ( pAnchoredObj->ClearedEnvironment() &&
2339                  pAnchoredObj->GetPageFrame() &&
2340                  pAnchoredObj->GetPageFrame() == pPageFrame )
2341             {
2342                 pAnchoredObj->UnlockPosition();
2343                 pAnchoredObj->SetClearedEnvironment( false );
2344             }
2345             // distinguish between writer fly frames and drawing objects
2346             if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) !=  nullptr )
2347             {
2348                 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
2349                 pFly->Invalidate_();
2350                 pFly->InvalidatePos_();
2351             }
2352             else
2353             {
2354                 pAnchoredObj->InvalidateObjPos();
2355             }
2356         } // end of loop on objects, which are connected to the frame
2357     }
2358 }
2359 
2360 // #i26945# - correct check, if anchored object is a lower
2361 // of the layout frame. E.g., anchor character text frame can be a follow text
2362 // frame.
2363 // #i44016# - add parameter <_bUnlockPosOfObjs> to
2364 // force an unlockposition call for the lower objects.
NotifyLowerObjs(const bool _bUnlockPosOfObjs)2365 void SwLayoutFrame::NotifyLowerObjs( const bool _bUnlockPosOfObjs )
2366 {
2367     // invalidate lower floating screen objects
2368     SwPageFrame* pPageFrame = FindPageFrame();
2369     if ( pPageFrame && pPageFrame->GetSortedObjs() )
2370     {
2371         SwSortedObjs& rObjs = *(pPageFrame->GetSortedObjs());
2372         for (SwAnchoredObject* pObj : rObjs)
2373         {
2374             // #i26945# - check, if anchored object is a lower
2375             // of the layout frame is changed to check, if its anchor frame
2376             // is a lower of the layout frame.
2377             // determine the anchor frame - usually it's the anchor frame,
2378             // for at-character/as-character anchored objects the anchor character
2379             // text frame is taken.
2380             const SwFrame* pAnchorFrame = pObj->GetAnchorFrameContainingAnchPos();
2381             if ( dynamic_cast<const SwFlyFrame*>( pObj) !=  nullptr )
2382             {
2383                 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObj);
2384 
2385                 if ( pFly->getFrameArea().Left() == FAR_AWAY )
2386                     continue;
2387 
2388                 if ( pFly->IsAnLower( this ) )
2389                     continue;
2390 
2391                 // #i26945# - use <pAnchorFrame> to check, if
2392                 // fly frame is lower of layout frame resp. if fly frame is
2393                 // at a different page registered as its anchor frame is on.
2394                 const bool bLow = IsAnLower( pAnchorFrame );
2395                 if ( bLow || pAnchorFrame->FindPageFrame() != pPageFrame )
2396                 {
2397                     pFly->Invalidate_( pPageFrame );
2398                     if ( !bLow || pFly->IsFlyAtContentFrame() )
2399                     {
2400                         // #i44016#
2401                         if ( _bUnlockPosOfObjs )
2402                         {
2403                             pFly->UnlockPosition();
2404                         }
2405                         pFly->InvalidatePos_();
2406                     }
2407                     else
2408                         pFly->InvalidatePrt_();
2409                 }
2410             }
2411             else
2412             {
2413                 OSL_ENSURE( dynamic_cast<const SwAnchoredDrawObject*>( pObj) !=  nullptr,
2414                         "<SwLayoutFrame::NotifyFlys() - anchored object of unexpected type" );
2415                 // #i26945# - use <pAnchorFrame> to check, if
2416                 // fly frame is lower of layout frame resp. if fly frame is
2417                 // at a different page registered as its anchor frame is on.
2418                 if ( IsAnLower( pAnchorFrame ) ||
2419                      pAnchorFrame->FindPageFrame() != pPageFrame )
2420                 {
2421                     // #i44016#
2422                     if ( _bUnlockPosOfObjs )
2423                     {
2424                         pObj->UnlockPosition();
2425                     }
2426                     pObj->InvalidateObjPos();
2427                 }
2428             }
2429         }
2430     }
2431 }
2432 
NotifyDrawObj()2433 void SwFlyFrame::NotifyDrawObj()
2434 {
2435     SwVirtFlyDrawObj* pObj = GetVirtDrawObj();
2436     pObj->SetRect();
2437     pObj->SetRectsDirty();
2438     pObj->SetChanged();
2439     pObj->BroadcastObjectChange();
2440 
2441     if ( GetFormat()->GetSurround().IsContour() )
2442     {
2443         ClrContourCache( pObj );
2444     }
2445     else if(IsFlyFreeFrame() && static_cast< const SwFlyFreeFrame* >(this)->supportsAutoContour())
2446     {
2447         // RotateFlyFrame3: Also need to clear when changes happen
2448         // Caution: isTransformableSwFrame is already reset when resetting rotation, so
2449         // *additionally* reset in SwFlyFreeFrame::MakeAll when no more rotation
2450         ClrContourCache( pObj );
2451     }
2452 }
2453 
CalcRel(const SwFormatFrameSize & rSz) const2454 Size SwFlyFrame::CalcRel( const SwFormatFrameSize &rSz ) const
2455 {
2456     Size aRet( rSz.GetSize() );
2457 
2458     const SwFrame *pRel = IsFlyLayFrame() ? GetAnchorFrame() : GetAnchorFrame()->GetUpper();
2459     if( pRel ) // LAYER_IMPL
2460     {
2461         long nRelWidth = LONG_MAX, nRelHeight = LONG_MAX;
2462         const SwViewShell *pSh = getRootFrame()->GetCurrShell();
2463         if ( ( pRel->IsBodyFrame() || pRel->IsPageFrame() ) &&
2464              pSh && pSh->GetViewOptions()->getBrowseMode() &&
2465              pSh->VisArea().HasArea() )
2466         {
2467             nRelWidth  = pSh->GetBrowseWidth();
2468             nRelHeight = pSh->VisArea().Height();
2469             Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
2470             nRelWidth  = std::min( nRelWidth,  pRel->getFramePrintArea().Width() );
2471             nRelHeight -= 2*aBorder.Height();
2472             nRelHeight = std::min( nRelHeight, pRel->getFramePrintArea().Height() );
2473         }
2474 
2475         // At the moment only the "== PAGE_FRAME" and "!= PAGE_FRAME" cases are handled.
2476         // When size is a relative to page size, ignore size of SwBodyFrame.
2477         if (rSz.GetWidthPercentRelation() != text::RelOrientation::PAGE_FRAME)
2478             nRelWidth  = std::min( nRelWidth,  pRel->getFramePrintArea().Width() );
2479         else if ( pRel->IsPageFrame() )
2480             nRelWidth  = std::min( nRelWidth,  pRel->getFrameArea().Width() );
2481 
2482         if (rSz.GetHeightPercentRelation() != text::RelOrientation::PAGE_FRAME)
2483             nRelHeight = std::min( nRelHeight, pRel->getFramePrintArea().Height() );
2484         else if ( pRel->IsPageFrame() )
2485             nRelHeight = std::min( nRelHeight, pRel->getFrameArea().Height() );
2486 
2487         if( !pRel->IsPageFrame() )
2488         {
2489             const SwPageFrame* pPage = FindPageFrame();
2490             if( pPage )
2491             {
2492                 if (rSz.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME)
2493                     // Ignore margins of pPage.
2494                     nRelWidth  = std::min( nRelWidth,  pPage->getFrameArea().Width() );
2495                 else
2496                     nRelWidth  = std::min( nRelWidth,  pPage->getFramePrintArea().Width() );
2497                 if (rSz.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME)
2498                     // Ignore margins of pPage.
2499                     nRelHeight = std::min( nRelHeight, pPage->getFrameArea().Height() );
2500                 else
2501                     nRelHeight = std::min( nRelHeight, pPage->getFramePrintArea().Height() );
2502             }
2503         }
2504 
2505         if ( rSz.GetWidthPercent() && rSz.GetWidthPercent() != SwFormatFrameSize::SYNCED )
2506             aRet.setWidth( nRelWidth * rSz.GetWidthPercent() / 100 );
2507         if ( rSz.GetHeightPercent() && rSz.GetHeightPercent() != SwFormatFrameSize::SYNCED )
2508             aRet.setHeight( nRelHeight * rSz.GetHeightPercent() / 100 );
2509 
2510         if ( rSz.GetWidthPercent() == SwFormatFrameSize::SYNCED )
2511         {
2512             aRet.setWidth( aRet.Width() * ( aRet.Height()) );
2513             aRet.setWidth( aRet.Width() / ( rSz.GetHeight()) );
2514         }
2515         else if ( rSz.GetHeightPercent() == SwFormatFrameSize::SYNCED )
2516         {
2517             aRet.setHeight( aRet.Height() * ( aRet.Width()) );
2518             aRet.setHeight( aRet.Height() / ( rSz.GetWidth()) );
2519         }
2520     }
2521     return aRet;
2522 }
2523 
lcl_CalcAutoWidth(const SwLayoutFrame & rFrame)2524 static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame )
2525 {
2526     SwTwips nRet = 0;
2527     SwTwips nMin = 0;
2528     const SwFrame* pFrame = rFrame.Lower();
2529 
2530     // No autowidth defined for columned frames
2531     if ( !pFrame || pFrame->IsColumnFrame() )
2532         return nRet;
2533 
2534     while ( pFrame )
2535     {
2536         if ( pFrame->IsSctFrame() )
2537         {
2538             nMin = lcl_CalcAutoWidth( *static_cast<const SwSectionFrame*>(pFrame) );
2539         }
2540         if ( pFrame->IsTextFrame() )
2541         {
2542             nMin = const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pFrame))->CalcFitToContent();
2543             const SvxLRSpaceItem &rSpace =
2544                 static_cast<const SwTextFrame*>(pFrame)->GetTextNodeForParaProps()->GetSwAttrSet().GetLRSpace();
2545             if (!static_cast<const SwTextFrame*>(pFrame)->IsLocked())
2546                 nMin += rSpace.GetRight() + rSpace.GetTextLeft() + rSpace.GetTextFirstLineOfst();
2547         }
2548         else if ( pFrame->IsTabFrame() )
2549         {
2550             const SwFormatFrameSize& rTableFormatSz = static_cast<const SwTabFrame*>(pFrame)->GetTable()->GetFrameFormat()->GetFrameSize();
2551             if ( USHRT_MAX == rTableFormatSz.GetSize().Width() ||
2552                  text::HoriOrientation::NONE == static_cast<const SwTabFrame*>(pFrame)->GetFormat()->GetHoriOrient().GetHoriOrient() )
2553             {
2554                 const SwPageFrame* pPage = rFrame.FindPageFrame();
2555                 // auto width table
2556                 nMin = pFrame->GetUpper()->IsVertical() ?
2557                     pPage->getFramePrintArea().Height() :
2558                     pPage->getFramePrintArea().Width();
2559             }
2560             else
2561             {
2562                 nMin = rTableFormatSz.GetSize().Width();
2563             }
2564         }
2565 
2566         if ( nMin > nRet )
2567             nRet = nMin;
2568 
2569         pFrame = pFrame->GetNext();
2570     }
2571 
2572     return nRet;
2573 }
2574 
2575 /// OD 16.04.2003 #i13147# - If called for paint and the <SwNoTextFrame> contains
2576 /// a graphic, load of intrinsic graphic has to be avoided.
GetContour(tools::PolyPolygon & rContour,const bool _bForPaint) const2577 bool SwFlyFrame::GetContour( tools::PolyPolygon&   rContour,
2578                            const bool _bForPaint ) const
2579 {
2580     vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
2581     bool bRet = false;
2582     const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame());
2583 
2584     if(bIsCandidate)
2585     {
2586         if(GetFormat()->GetSurround().IsContour())
2587         {
2588             SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwNoTextFrame*>(Lower())->GetNode()));
2589             // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
2590             // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic
2591             // node and method is called for paint.
2592             std::unique_ptr<GraphicObject> xTmpGrfObj;
2593             const GraphicObject* pGrfObj = nullptr;
2594             const SwGrfNode* pGrfNd = pNd->GetGrfNode();
2595             if ( pGrfNd && _bForPaint )
2596             {
2597                 pGrfObj = &(pGrfNd->GetGrfObj());
2598             }
2599             else
2600             {
2601                 xTmpGrfObj.reset(new GraphicObject(pNd->GetGraphic()));
2602                 pGrfObj = xTmpGrfObj.get();
2603             }
2604             assert(pGrfObj && "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>.");
2605             if (pGrfObj->GetType() != GraphicType::NONE)
2606             {
2607                 if( !pNd->HasContour() )
2608                 {
2609                     // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
2610                     // during paint. Thus, return (value of <bRet> should be <false>).
2611                     if ( pGrfNd && _bForPaint )
2612                     {
2613                         OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." );
2614                         return bRet;
2615                     }
2616                     pNd->CreateContour();
2617                 }
2618                 pNd->GetContour( rContour );
2619                 // The Node holds the Polygon matching the original size of the graphic
2620                 // We need to include the scaling here
2621                 SwRect aClip;
2622                 SwRect aOrig;
2623                 Lower()->Calc(pRenderContext);
2624                 static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig );
2625                 // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
2626                 // in order to avoid that graphic has to be loaded for contour scale.
2627                 //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() );
2628                 {
2629                     OutputDevice*   pOutDev = Application::GetDefaultDevice();
2630                     const MapMode   aDispMap( MapUnit::MapTwip );
2631                     const MapMode   aGrfMap( pGrfObj->GetPrefMapMode() );
2632                     const Size      aGrfSize( pGrfObj->GetPrefSize() );
2633                     Size            aOrgSize;
2634                     Point           aNewPoint;
2635                     bool            bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;
2636 
2637                     if ( bPixelMap )
2638                         aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
2639                     else
2640                         aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap );
2641 
2642                     if ( aOrgSize.Width() && aOrgSize.Height() )
2643                     {
2644                         double fScaleX = static_cast<double>(aOrig.Width()) / aOrgSize.Width();
2645                         double fScaleY = static_cast<double>(aOrig.Height()) / aOrgSize.Height();
2646 
2647                         for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
2648                         {
2649                             tools::Polygon& rPoly = rContour[ j ];
2650 
2651                             for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
2652                             {
2653                                 if ( bPixelMap )
2654                                     aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap  );
2655                                 else
2656                                     aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap  );
2657 
2658                                 rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) );
2659                             }
2660                         }
2661                     }
2662                 }
2663                 // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
2664                 xTmpGrfObj.reset();
2665                 rContour.Move( aOrig.Left(), aOrig.Top() );
2666                 if( !aClip.Width() )
2667                     aClip.Width( 1 );
2668                 if( !aClip.Height() )
2669                     aClip.Height( 1 );
2670                 rContour.Clip( aClip.SVRect() );
2671                 rContour.Optimize(PolyOptimizeFlags::CLOSE);
2672                 bRet = true;
2673             }
2674         }
2675         else
2676         {
2677             const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(this));
2678 
2679             if(nullptr != pSwFlyFreeFrame &&
2680                 pSwFlyFreeFrame->supportsAutoContour() &&
2681                 // isTransformableSwFrame already used in supportsAutoContour(), but
2682                 // better check twice when it may get changed there...
2683                 pSwFlyFreeFrame->isTransformableSwFrame())
2684             {
2685                 // RotateFlyFrame: use untransformed SwFrame to allow text floating around.
2686                 // Will be transformed below
2687                 const TransformableSwFrame* pTransformableSwFrame(pSwFlyFreeFrame->getTransformableSwFrame());
2688                 const SwRect aFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
2689                 rContour = tools::PolyPolygon(tools::Polygon(aFrameArea.SVRect()));
2690                 bRet = (0 != rContour.Count());
2691             }
2692         }
2693 
2694         if(bRet && 0 != rContour.Count())
2695         {
2696             const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(this));
2697 
2698             if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->isTransformableSwFrame())
2699             {
2700                 // Need to adapt contour to transformation
2701                 basegfx::B2DVector aScale, aTranslate;
2702                 double fRotate, fShearX;
2703                 getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
2704 
2705                 if(!basegfx::fTools::equalZero(fRotate))
2706                 {
2707                     basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon());
2708                     const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
2709                     const basegfx::B2DHomMatrix aRotateAroundCenter(
2710                         basegfx::utils::createRotateAroundPoint(
2711                             aCenter.getX(),
2712                             aCenter.getY(),
2713                             fRotate));
2714                     aSource.transform(aRotateAroundCenter);
2715                     rContour = tools::PolyPolygon(aSource);
2716                 }
2717             }
2718         }
2719     }
2720 
2721     return bRet;
2722 }
2723 
2724 // OD 2004-03-25 #i26791#
GetVirtDrawObj() const2725 const SwVirtFlyDrawObj* SwFlyFrame::GetVirtDrawObj() const
2726 {
2727     return static_cast<const SwVirtFlyDrawObj*>(GetDrawObj());
2728 }
GetVirtDrawObj()2729 SwVirtFlyDrawObj* SwFlyFrame::GetVirtDrawObj()
2730 {
2731     return static_cast<SwVirtFlyDrawObj*>(DrawObj());
2732 }
2733 
2734 // OD 2004-03-24 #i26791# - implementation of pure virtual method declared in
2735 // base class <SwAnchoredObject>
2736 
InvalidateObjPos()2737 void SwFlyFrame::InvalidateObjPos()
2738 {
2739     InvalidatePos();
2740     // #i68520#
2741     InvalidateObjRectWithSpaces();
2742 }
2743 
GetFrameFormat()2744 SwFrameFormat& SwFlyFrame::GetFrameFormat()
2745 {
2746     OSL_ENSURE( GetFormat(),
2747             "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
2748     return *GetFormat();
2749 }
GetFrameFormat() const2750 const SwFrameFormat& SwFlyFrame::GetFrameFormat() const
2751 {
2752     OSL_ENSURE( GetFormat(),
2753             "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
2754     return *GetFormat();
2755 }
2756 
GetObjRect() const2757 SwRect SwFlyFrame::GetObjRect() const
2758 {
2759     return getFrameArea();
2760 }
2761 
2762 // #i70122#
2763 // for Writer fly frames the bounding rectangle equals the object rectangles
GetObjBoundRect() const2764 SwRect SwFlyFrame::GetObjBoundRect() const
2765 {
2766     return GetObjRect();
2767 }
2768 
2769 // #i68520#
SetObjTop_(const SwTwips _nTop)2770 bool SwFlyFrame::SetObjTop_( const SwTwips _nTop )
2771 {
2772     const bool bChanged( getFrameArea().Pos().getY() != _nTop );
2773     SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2774     aFrm.Pos().setY(_nTop);
2775 
2776     return bChanged;
2777 }
SetObjLeft_(const SwTwips _nLeft)2778 bool SwFlyFrame::SetObjLeft_( const SwTwips _nLeft )
2779 {
2780     const bool bChanged( getFrameArea().Pos().getX() != _nLeft );
2781     SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2782     aFrm.Pos().setX(_nLeft);
2783 
2784     return bChanged;
2785 }
2786 
2787 /** method to assure that anchored object is registered at the correct
2788     page frame
2789 
2790     OD 2004-07-02 #i28701#
2791 */
RegisterAtCorrectPage()2792 void SwFlyFrame::RegisterAtCorrectPage()
2793 {
2794     // default behaviour is to do nothing.
2795 }
2796 
2797 /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
2798 
2799     OD 2004-05-11 #i28701#
2800 */
IsFormatPossible() const2801 bool SwFlyFrame::IsFormatPossible() const
2802 {
2803     return SwAnchoredObject::IsFormatPossible() &&
2804            !IsLocked() && !IsColLocked();
2805 }
2806 
GetAnchoredObjects(std::vector<SwAnchoredObject * > & aVector,const SwFormat & rFormat)2807 void SwFlyFrame::GetAnchoredObjects( std::vector<SwAnchoredObject*>& aVector, const SwFormat& rFormat )
2808 {
2809     SwIterator<SwFlyFrame,SwFormat> aIter( rFormat );
2810     for( SwFlyFrame* pFlyFrame = aIter.First(); pFlyFrame; pFlyFrame = aIter.Next() )
2811         aVector.push_back( pFlyFrame );
2812 }
2813 
GetFormat() const2814 const SwFlyFrameFormat * SwFlyFrame::GetFormat() const
2815 {
2816     return static_cast< const SwFlyFrameFormat * >( GetDep() );
2817 }
2818 
GetFormat()2819 SwFlyFrameFormat * SwFlyFrame::GetFormat()
2820 {
2821     return static_cast< SwFlyFrameFormat * >( GetDep() );
2822 }
2823 
Calc(vcl::RenderContext * pRenderContext) const2824 void SwFlyFrame::Calc(vcl::RenderContext* pRenderContext) const
2825 {
2826     if ( !m_bValidContentPos )
2827         const_cast<SwFlyFrame*>(this)->PrepareMake(pRenderContext);
2828     else
2829         SwLayoutFrame::Calc(pRenderContext);
2830 }
2831 
CalcContentHeight(const SwBorderAttrs * pAttrs,const SwTwips nMinHeight,const SwTwips nUL)2832 SwTwips SwFlyFrame::CalcContentHeight(const SwBorderAttrs *pAttrs, const SwTwips nMinHeight, const SwTwips nUL)
2833 {
2834     SwRectFnSet aRectFnSet(this);
2835     SwTwips nHeight = 0;
2836     if ( Lower() )
2837     {
2838         if ( Lower()->IsColumnFrame() )
2839         {
2840             FormatWidthCols( *pAttrs, nUL, nMinHeight );
2841             nHeight = aRectFnSet.GetHeight(Lower()->getFrameArea());
2842         }
2843         else
2844         {
2845             SwFrame *pFrame = Lower();
2846             while ( pFrame )
2847             {
2848                 nHeight += aRectFnSet.GetHeight(pFrame->getFrameArea());
2849                 if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
2850                 // This TextFrame would like to be a bit larger
2851                     nHeight += static_cast<SwTextFrame*>(pFrame)->GetParHeight()
2852                             - aRectFnSet.GetHeight(pFrame->getFramePrintArea());
2853                 else if( pFrame->IsSctFrame() && static_cast<SwSectionFrame*>(pFrame)->IsUndersized() )
2854                     nHeight += static_cast<SwSectionFrame*>(pFrame)->Undersize();
2855                 pFrame = pFrame->GetNext();
2856             }
2857         }
2858         if ( GetDrawObjs() )
2859         {
2860             const size_t nCnt = GetDrawObjs()->size();
2861             SwTwips nTop = aRectFnSet.GetTop(getFrameArea());
2862             SwTwips nBorder = aRectFnSet.GetHeight(getFrameArea()) -
2863             aRectFnSet.GetHeight(getFramePrintArea());
2864             for ( size_t i = 0; i < nCnt; ++i )
2865             {
2866                 SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
2867                 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) !=  nullptr )
2868                 {
2869                     SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
2870                     // OD 06.11.2003 #i22305# - consider
2871                     // only Writer fly frames, which follow the text flow.
2872                     if ( pFly->IsFlyLayFrame() &&
2873                         pFly->getFrameArea().Top() != FAR_AWAY &&
2874                         pFly->GetFormat()->GetFollowTextFlow().GetValue() )
2875                     {
2876                         SwTwips nDist = -aRectFnSet.BottomDist( pFly->getFrameArea(), nTop );
2877                         if( nDist > nBorder + nHeight )
2878                             nHeight = nDist - nBorder;
2879                     }
2880                 }
2881             }
2882         }
2883     }
2884     return nHeight;
2885 }
2886 
2887 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2888