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

Generated by: LCOV version 1.10