LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/layout - layouter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 64 225 28.4 %
Date: 2012-12-27 Functions: 13 34 38.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      21             : #include "layouter.hxx"
      22             : #include "doc.hxx"
      23             : #include "sectfrm.hxx"
      24             : #include "ftnboss.hxx"
      25             : #include "cntfrm.hxx"
      26             : #include "pagefrm.hxx"
      27             : #include "ftnfrm.hxx"
      28             : #include "txtfrm.hxx"
      29             : 
      30             : // #i28701#
      31             : #include <movedfwdfrmsbyobjpos.hxx>
      32             : // #i35911#
      33             : #include <objstmpconsiderwrapinfl.hxx>
      34             : 
      35             : #define LOOP_DETECT 250
      36             : 
      37             : class SwLooping
      38             : {
      39             :     sal_uInt16 nMinPage;
      40             :     sal_uInt16 nMaxPage;
      41             :     sal_uInt16 nCount;
      42             :     sal_uInt16 mnLoopControlStage;
      43             : public:
      44             :     SwLooping( SwPageFrm* pPage );
      45             :     void Control( SwPageFrm* pPage );
      46             :     void Drastic( SwFrm* pFrm );
      47           0 :     bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
      48             : };
      49             : 
      50             : class SwEndnoter
      51             : {
      52             :     SwLayouter* pMaster;
      53             :     SwSectionFrm* pSect;
      54             :     SwFtnFrms*    pEndArr;
      55             : public:
      56           0 :     SwEndnoter( SwLayouter* pLay )
      57           0 :         : pMaster( pLay ), pSect( NULL ), pEndArr( NULL ) {}
      58           0 :     ~SwEndnoter() { delete pEndArr; }
      59             :     void CollectEndnotes( SwSectionFrm* pSct );
      60             :     void CollectEndnote( SwFtnFrm* pFtn );
      61           0 :     const SwSectionFrm* GetSect() const { return pSect; }
      62             :     void InsertEndnotes();
      63           0 :     bool HasEndnotes() const { return pEndArr && !pEndArr->empty(); }
      64             : };
      65             : 
      66           0 : void SwEndnoter::CollectEndnotes( SwSectionFrm* pSct )
      67             : {
      68             :     OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
      69           0 :     if( !pSect )
      70           0 :         pSect = pSct;
      71           0 :     else if( pSct != pSect )
      72           0 :         return;
      73           0 :     pSect->CollectEndnotes( pMaster );
      74             : }
      75             : 
      76           0 : void SwEndnoter::CollectEndnote( SwFtnFrm* pFtn )
      77             : {
      78           0 :     if( pEndArr && pEndArr->end() != std::find( pEndArr->begin(), pEndArr->end(), pFtn ) )
      79           0 :         return;
      80             : 
      81           0 :     if( pFtn->GetUpper() )
      82             :     {
      83             :         // pFtn is the master, he incorporates its follows
      84           0 :         SwFtnFrm *pNxt = pFtn->GetFollow();
      85           0 :         while ( pNxt )
      86             :         {
      87           0 :             SwFrm *pCnt = pNxt->ContainsAny();
      88           0 :             if ( pCnt )
      89             :             {
      90           0 :                 do
      91           0 :                 {   SwFrm *pNxtCnt = pCnt->GetNext();
      92           0 :                     pCnt->Cut();
      93           0 :                     pCnt->Paste( pFtn );
      94           0 :                     pCnt = pNxtCnt;
      95             :                 } while ( pCnt );
      96             :             }
      97             :             else
      98             :             { OSL_ENSURE( pNxt->Lower() && pNxt->Lower()->IsSctFrm(),
      99             :                         "Endnote without content?" );
     100           0 :                 pNxt->Cut();
     101           0 :                 delete pNxt;
     102             :             }
     103           0 :             pNxt = pFtn->GetFollow();
     104             :         }
     105           0 :         if( pFtn->GetMaster() )
     106           0 :             return;
     107           0 :         pFtn->Cut();
     108             :     }
     109           0 :     else if( pEndArr )
     110             :     {
     111           0 :         for ( sal_uInt16 i = 0; i < pEndArr->size(); ++i )
     112             :         {
     113           0 :             SwFtnFrm *pEndFtn = (*pEndArr)[i];
     114           0 :             if( pEndFtn->GetAttr() == pFtn->GetAttr() )
     115             :             {
     116           0 :                 delete pFtn;
     117           0 :                 return;
     118             :             }
     119             :         }
     120             :     }
     121           0 :     if( !pEndArr )
     122           0 :         pEndArr = new SwFtnFrms;  // deleted from the SwLayouter
     123           0 :     pEndArr->push_back( pFtn );
     124             : }
     125             : 
     126           0 : void SwEndnoter::InsertEndnotes()
     127             : {
     128           0 :     if( !pSect )
     129           0 :         return;
     130           0 :     if( !pEndArr || pEndArr->empty() )
     131             :     {
     132           0 :         pSect = NULL;
     133           0 :         return;
     134             :     }
     135             :     OSL_ENSURE( pSect->Lower() && pSect->Lower()->IsFtnBossFrm(),
     136             :             "InsertEndnotes: Where's my column?" );
     137           0 :     SwFrm* pRef = pSect->FindLastCntnt( FINDMODE_MYLAST );
     138             :     SwFtnBossFrm *pBoss = pRef ? pRef->FindFtnBossFrm()
     139           0 :                                : (SwFtnBossFrm*)pSect->Lower();
     140           0 :     pBoss->_MoveFtns( *pEndArr );
     141           0 :     delete pEndArr;
     142           0 :     pEndArr = NULL;
     143           0 :     pSect = NULL;
     144             : }
     145             : 
     146         438 : SwLooping::SwLooping( SwPageFrm* pPage )
     147             : {
     148             :     OSL_ENSURE( pPage, "Where's my page?" );
     149         438 :     nMinPage = pPage->GetPhyPageNum();
     150         438 :     nMaxPage = nMinPage;
     151         438 :     nCount = 0;
     152         438 :     mnLoopControlStage = 0;
     153         438 : }
     154             : 
     155           0 : void SwLooping::Drastic( SwFrm* pFrm )
     156             : {
     157           0 :     while( pFrm )
     158             :     {
     159           0 :         pFrm->ValidateThisAndAllLowers( mnLoopControlStage );
     160           0 :         pFrm = pFrm->GetNext();
     161             :     }
     162           0 : }
     163             : 
     164         433 : void SwLooping::Control( SwPageFrm* pPage )
     165             : {
     166         433 :     if( !pPage )
     167         617 :         return;
     168         249 :     sal_uInt16 nNew = pPage->GetPhyPageNum();
     169         249 :     if( nNew > nMaxPage )
     170          15 :         nMaxPage = nNew;
     171         249 :     if( nNew < nMinPage )
     172             :     {
     173           0 :         nMinPage = nNew;
     174           0 :         nMaxPage = nNew;
     175           0 :         nCount = 0;
     176           0 :         mnLoopControlStage = 0;
     177             :     }
     178         249 :     else if( nNew > nMinPage + 2 )
     179             :     {
     180           0 :         nMinPage = nNew - 2;
     181           0 :         nMaxPage = nNew;
     182           0 :         nCount = 0;
     183           0 :         mnLoopControlStage = 0;
     184             :     }
     185         249 :     else if( ++nCount > LOOP_DETECT )
     186             :     {
     187             : #if OSL_DEBUG_LEVEL > 1
     188             :         static bool bNoLouie = false;
     189             :         if( bNoLouie )
     190             :             return;
     191             : 
     192             :         // FME 2007-08-30 #i81146# new loop control
     193             :         OSL_ENSURE( 0 != mnLoopControlStage, "Looping Louie: Stage 1!" );
     194             :         OSL_ENSURE( 1 != mnLoopControlStage, "Looping Louie: Stage 2!!" );
     195             :         OSL_ENSURE( 2 >  mnLoopControlStage, "Looping Louie: Stage 3!!!" );
     196             : #endif
     197             : 
     198           0 :         Drastic( pPage->Lower() );
     199           0 :         if( nNew > nMinPage && pPage->GetPrev() )
     200           0 :             Drastic( ((SwPageFrm*)pPage->GetPrev())->Lower() );
     201           0 :         if( nNew < nMaxPage && pPage->GetNext() )
     202           0 :             Drastic( ((SwPageFrm*)pPage->GetNext())->Lower() );
     203             : 
     204           0 :         ++mnLoopControlStage;
     205           0 :         nCount = 0;
     206             :     }
     207             : }
     208             : 
     209             : /*************************************************************************
     210             : |*
     211             : |*  SwLayouter::SwLayouter()
     212             : |*
     213             : |*************************************************************************/
     214             : 
     215         236 : SwLayouter::SwLayouter()
     216             :         : pEndnoter( NULL ),
     217             :           pLooping( NULL ),
     218             :           // #i28701#
     219             :           mpMovedFwdFrms( 0L ),
     220             :           // #i35911#
     221         236 :           mpObjsTmpConsiderWrapInfl( 0L )
     222             : {
     223         236 : }
     224             : 
     225         126 : SwLayouter::~SwLayouter()
     226             : {
     227          63 :     delete pEndnoter;
     228          63 :     delete pLooping;
     229             :     // #i28701#
     230          63 :     delete mpMovedFwdFrms;
     231          63 :     mpMovedFwdFrms = 0L;
     232             :     // #i35911#
     233          63 :     delete mpObjsTmpConsiderWrapInfl;
     234          63 :     mpObjsTmpConsiderWrapInfl = 0L;
     235          63 : }
     236             : 
     237           0 : void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
     238             : {
     239           0 :     if( !pEndnoter )
     240           0 :         pEndnoter = new SwEndnoter( this );
     241           0 :     pEndnoter->CollectEndnotes( pSect );
     242           0 : }
     243             : 
     244           0 : bool SwLayouter::HasEndnotes() const
     245             : {
     246           0 :     return pEndnoter->HasEndnotes();
     247             : }
     248             : 
     249           0 : void SwLayouter::CollectEndnote( SwFtnFrm* pFtn )
     250             : {
     251           0 :     pEndnoter->CollectEndnote( pFtn );
     252           0 : }
     253             : 
     254           0 : void SwLayouter::InsertEndnotes( SwSectionFrm* pSect )
     255             : {
     256           0 :     if( !pEndnoter || pEndnoter->GetSect() != pSect )
     257           0 :         return;
     258           0 :     pEndnoter->InsertEndnotes();
     259             : }
     260             : 
     261         433 : void SwLayouter::LoopControl( SwPageFrm* pPage, sal_uInt8 )
     262             : {
     263             :     OSL_ENSURE( pLooping, "Looping: Lost control" );
     264         433 :     pLooping->Control( pPage );
     265         433 : }
     266             : 
     267           0 : void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTxtFrm& rFrm )
     268             : {
     269           0 :     if ( pLooping && pLooping->IsLoopingLouieLight() )
     270             :     {
     271             : #if OSL_DEBUG_LEVEL > 1
     272             :         OSL_FAIL( "Looping Louie (Light): Fixating fractious frame" );
     273             : #endif
     274           0 :         SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
     275             :     }
     276           0 : }
     277             : 
     278         438 : sal_Bool SwLayouter::StartLooping( SwPageFrm* pPage )
     279             : {
     280         438 :     if( pLooping )
     281           0 :         return sal_False;
     282         438 :     pLooping = new SwLooping( pPage );
     283         438 :     return sal_True;
     284             : }
     285             : 
     286         438 : void SwLayouter::EndLoopControl()
     287             : {
     288         438 :     delete pLooping;
     289         438 :     pLooping = NULL;
     290         438 : }
     291             : 
     292           0 : void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect )
     293             : {
     294             :     OSL_ENSURE( pDoc, "No doc, no fun" );
     295           0 :     if( !pDoc->GetLayouter() )
     296           0 :         pDoc->SetLayouter( new SwLayouter() );
     297           0 :     pDoc->GetLayouter()->_CollectEndnotes( pSect );
     298           0 : }
     299             : 
     300           0 : sal_Bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn )
     301             : {
     302           0 :     if( !pDoc->GetLayouter() )
     303           0 :         return sal_False;
     304           0 :     SwLayouter *pLayouter = pDoc->GetLayouter();
     305           0 :     if( pLayouter->pEndnoter && pLayouter->pEndnoter->GetSect() && pSect &&
     306           0 :         ( pLayouter->pEndnoter->GetSect()->IsAnFollow( pSect ) ||
     307           0 :           pSect->IsAnFollow( pLayouter->pEndnoter->GetSect() ) ) )
     308             :     {
     309           0 :         if( pFtn )
     310           0 :             pLayouter->CollectEndnote( pFtn );
     311           0 :         return sal_True;
     312             :     }
     313           0 :     return sal_False;
     314             : }
     315             : 
     316         438 : sal_Bool SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage )
     317             : {
     318             :     OSL_ENSURE( pDoc, "No doc, no fun" );
     319         438 :     if( !pDoc->GetLayouter() )
     320         236 :         pDoc->SetLayouter( new SwLayouter() );
     321         438 :     return !pDoc->GetLayouter()->pLooping &&
     322         438 :             pDoc->GetLayouter()->StartLooping( pPage );
     323             : }
     324             : 
     325             : // #i28701#
     326             : // -----------------------------------------------------------------------------
     327             : // methods to manage text frames, which are moved forward by the positioning
     328             : // of its anchored objects
     329             : // -----------------------------------------------------------------------------
     330       79452 : void SwLayouter::ClearMovedFwdFrms( const SwDoc& _rDoc )
     331             : {
     332       79596 :     if ( _rDoc.GetLayouter() &&
     333         144 :          _rDoc.GetLayouter()->mpMovedFwdFrms )
     334             :     {
     335           0 :         _rDoc.GetLayouter()->mpMovedFwdFrms->Clear();
     336             :     }
     337       79452 : }
     338             : 
     339           0 : void SwLayouter::InsertMovedFwdFrm( const SwDoc& _rDoc,
     340             :                                     const SwTxtFrm& _rMovedFwdFrmByObjPos,
     341             :                                     const sal_uInt32 _nToPageNum )
     342             : {
     343           0 :     if ( !_rDoc.GetLayouter() )
     344             :     {
     345           0 :         const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
     346             :     }
     347             : 
     348           0 :     if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
     349             :     {
     350           0 :         const_cast<SwDoc&>(_rDoc).GetLayouter()->mpMovedFwdFrms =
     351           0 :                                                 new SwMovedFwdFrmsByObjPos();
     352             :     }
     353             : 
     354           0 :     _rDoc.GetLayouter()->mpMovedFwdFrms->Insert( _rMovedFwdFrmByObjPos,
     355           0 :                                                  _nToPageNum );
     356           0 : }
     357             : 
     358             : // #i40155#
     359           0 : void SwLayouter::RemoveMovedFwdFrm( const SwDoc& _rDoc,
     360             :                                     const SwTxtFrm& _rTxtFrm )
     361             : {
     362             :     sal_uInt32 nDummy;
     363           0 :     if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc, _rTxtFrm, nDummy ) )
     364             :     {
     365           0 :         _rDoc.GetLayouter()->mpMovedFwdFrms->Remove( _rTxtFrm );
     366             :     }
     367           0 : }
     368             : 
     369         981 : bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc& _rDoc,
     370             :                                       const SwTxtFrm& _rTxtFrm,
     371             :                                       sal_uInt32& _ornToPageNum )
     372             : {
     373         981 :     if ( !_rDoc.GetLayouter() )
     374             :     {
     375         167 :         _ornToPageNum = 0;
     376         167 :         return false;
     377             :     }
     378         814 :     else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
     379             :     {
     380         814 :         _ornToPageNum = 0;
     381         814 :         return false;
     382             :     }
     383             :     else
     384             :     {
     385           0 :         return _rDoc.GetLayouter()->mpMovedFwdFrms->
     386           0 :                                 FrmMovedFwdByObjPos( _rTxtFrm, _ornToPageNum );
     387             :     }
     388             : }
     389             : // #i26945#
     390           0 : bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
     391             :                                             const SwRowFrm& _rRowFrm )
     392             : {
     393           0 :     if ( !_rDoc.GetLayouter() )
     394             :     {
     395           0 :         return false;
     396             :     }
     397           0 :     else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
     398             :     {
     399           0 :         return false;
     400             :     }
     401             :     else
     402             :     {
     403           0 :         return _rDoc.GetLayouter()->
     404           0 :                         mpMovedFwdFrms->DoesRowContainMovedFwdFrm( _rRowFrm );
     405             :     }
     406             : }
     407             : 
     408             : // #i35911#
     409       79452 : void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc )
     410             : {
     411       79596 :     if ( _rDoc.GetLayouter() &&
     412         144 :          _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
     413             :     {
     414           0 :         _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Clear();
     415             :     }
     416       79452 : }
     417           0 : void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
     418             :                                             const SwDoc& _rDoc,
     419             :                                             SwAnchoredObject& _rAnchoredObj )
     420             : {
     421           0 :     if ( !_rDoc.GetLayouter() )
     422             :     {
     423           0 :         const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
     424             :     }
     425             : 
     426           0 :     if ( !_rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
     427             :     {
     428           0 :         const_cast<SwDoc&>(_rDoc).GetLayouter()->mpObjsTmpConsiderWrapInfl =
     429           0 :                                 new SwObjsMarkedAsTmpConsiderWrapInfluence();
     430             :     }
     431             : 
     432           0 :     _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
     433           0 : }
     434             : 
     435         979 : void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm )
     436             : {
     437         979 :     if ( bCondition )
     438             :     {
     439           0 :         const SwDoc& rDoc = *rTxtFrm.GetAttrSet()->GetDoc();
     440           0 :         if ( rDoc.GetLayouter() )
     441             :         {
     442           0 :             const_cast<SwDoc&>(rDoc).GetLayouter()->LoopingLouieLight( rDoc, rTxtFrm );
     443             :         }
     444             :     }
     445         979 : }
     446             : 
     447             : // #i65250#
     448           0 : bool SwLayouter::MoveBwdSuppressed( const SwDoc& p_rDoc,
     449             :                                     const SwFlowFrm& p_rFlowFrm,
     450             :                                     const SwLayoutFrm& p_rNewUpperFrm )
     451             : {
     452           0 :     bool bMoveBwdSuppressed( false );
     453             : 
     454           0 :     if ( !p_rDoc.GetLayouter() )
     455             :     {
     456           0 :         const_cast<SwDoc&>(p_rDoc).SetLayouter( new SwLayouter() );
     457             :     }
     458             : 
     459             :     // create hash map key
     460             :     tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
     461           0 :     aMoveBwdLayoutInfo.mnFrmId = p_rFlowFrm.GetFrm()->GetFrmId();
     462           0 :     aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrm.Frm().Pos().X();
     463           0 :     aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrm.Frm().Pos().Y();
     464           0 :     aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrm.Frm().Width();
     465           0 :     aMoveBwdLayoutInfo.mnNewUpperHeight =  p_rNewUpperFrm.Frm().Height();
     466           0 :     SWRECTFN( (&p_rNewUpperFrm) )
     467           0 :     const SwFrm* pLastLower( p_rNewUpperFrm.Lower() );
     468           0 :     while ( pLastLower && pLastLower->GetNext() )
     469             :     {
     470           0 :         pLastLower = pLastLower->GetNext();
     471             :     }
     472             :     aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
     473             :             pLastLower
     474           0 :             ? (pLastLower->Frm().*fnRect->fnBottomDist)( (p_rNewUpperFrm.*fnRect->fnGetPrtBottom)() )
     475           0 :             : (p_rNewUpperFrm.Frm().*fnRect->fnGetHeight)();
     476             : 
     477             :     // check for moving backward suppress threshold
     478           0 :     const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
     479           0 :     if ( ++const_cast<SwDoc&>(p_rDoc).GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
     480             :                                                 cMoveBwdCountSuppressThreshold )
     481             :     {
     482           0 :         bMoveBwdSuppressed = true;
     483             :     }
     484             : 
     485           0 :     return bMoveBwdSuppressed;
     486             : }
     487             : 
     488       79452 : void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc& _rDoc )
     489             : {
     490       79452 :     if ( _rDoc.GetLayouter() )
     491         144 :         const_cast<SwDoc&>(_rDoc).GetLayouter()->maMoveBwdLayoutInfo.clear();
     492       79452 : }
     493             : 
     494             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10