1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 #include <objectformatter.hxx> 27 #include <objectformattertxtfrm.hxx> 28 #include <objectformatterlayfrm.hxx> 29 #include <anchoredobject.hxx> 30 #include <anchoreddrawobject.hxx> 31 #include <sortedobjs.hxx> 32 #include <pagefrm.hxx> 33 #include <flyfrms.hxx> 34 #include <txtfrm.hxx> 35 #include <layact.hxx> 36 #include <frmfmt.hxx> 37 #include <fmtanchr.hxx> 38 #include <doc.hxx> 39 40 #include <vector> 41 42 // ============================================================================= 43 // helper class <SwPageNumAndTypeOfAnchors> 44 // --> OD 2004-10-04 #i26945# - Additionally the type of the anchor text frame 45 // is collected - by type is meant 'master' or 'follow'. 46 // ============================================================================= 47 class SwPageNumAndTypeOfAnchors 48 { 49 private: 50 struct tEntry 51 { 52 SwAnchoredObject* mpAnchoredObj; 53 sal_uInt32 mnPageNumOfAnchor; 54 bool mbAnchoredAtMaster; 55 }; 56 57 std::vector< tEntry* > maObjList; 58 59 public: 60 inline SwPageNumAndTypeOfAnchors() 61 { 62 } 63 inline ~SwPageNumAndTypeOfAnchors() 64 { 65 for ( std::vector< tEntry* >::iterator aIter = maObjList.begin(); 66 aIter != maObjList.end(); ++aIter ) 67 { 68 delete (*aIter); 69 } 70 maObjList.clear(); 71 } 72 73 inline void Collect( SwAnchoredObject& _rAnchoredObj ) 74 { 75 tEntry* pNewEntry = new tEntry(); 76 pNewEntry->mpAnchoredObj = &_rAnchoredObj; 77 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()> 78 // is replaced by method <FindPageFrmOfAnchor()>. It's return value 79 // have to be checked. 80 SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor(); 81 if ( pPageFrmOfAnchor ) 82 { 83 pNewEntry->mnPageNumOfAnchor = pPageFrmOfAnchor->GetPhyPageNum(); 84 } 85 else 86 { 87 pNewEntry->mnPageNumOfAnchor = 0; 88 } 89 // <-- 90 // --> OD 2004-10-04 #i26945# - collect type of anchor 91 SwTxtFrm* pAnchorCharFrm = _rAnchoredObj.FindAnchorCharFrm(); 92 if ( pAnchorCharFrm ) 93 { 94 pNewEntry->mbAnchoredAtMaster = !pAnchorCharFrm->IsFollow(); 95 } 96 else 97 { 98 pNewEntry->mbAnchoredAtMaster = true; 99 } 100 // <-- 101 maObjList.push_back( pNewEntry ); 102 } 103 104 inline SwAnchoredObject* operator[]( sal_uInt32 _nIndex ) 105 { 106 SwAnchoredObject* bRetObj = 0L; 107 108 if ( _nIndex < Count()) 109 { 110 bRetObj = maObjList[_nIndex]->mpAnchoredObj; 111 } 112 113 return bRetObj; 114 } 115 116 inline sal_uInt32 GetPageNum( sal_uInt32 _nIndex ) 117 { 118 sal_uInt32 nRetPgNum = 0L; 119 120 if ( _nIndex < Count()) 121 { 122 nRetPgNum = maObjList[_nIndex]->mnPageNumOfAnchor; 123 } 124 125 return nRetPgNum; 126 } 127 128 // --> OD 2004-10-04 #i26945# 129 inline bool AnchoredAtMaster( sal_uInt32 _nIndex ) 130 { 131 bool bAnchoredAtMaster( true ); 132 133 if ( _nIndex < Count()) 134 { 135 bAnchoredAtMaster = maObjList[_nIndex]->mbAnchoredAtMaster; 136 } 137 138 return bAnchoredAtMaster; 139 } 140 // <-- 141 142 inline sal_uInt32 Count() const 143 { 144 return maObjList.size(); 145 } 146 }; 147 148 // ============================================================================= 149 // implementation of class <SwObjectFormatter> 150 // ============================================================================= 151 SwObjectFormatter::SwObjectFormatter( const SwPageFrm& _rPageFrm, 152 SwLayAction* _pLayAction, 153 const bool _bCollectPgNumOfAnchors ) 154 : mrPageFrm( _rPageFrm ), 155 mbFormatOnlyAsCharAnchored( false ), 156 mbConsiderWrapOnObjPos( _rPageFrm.GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ), 157 mpLayAction( _pLayAction ), 158 // --> OD 2004-10-04 #i26945# 159 mpPgNumAndTypeOfAnchors( _bCollectPgNumOfAnchors ? new SwPageNumAndTypeOfAnchors() : 0L ) 160 // <-- 161 { 162 } 163 164 SwObjectFormatter::~SwObjectFormatter() 165 { 166 delete mpPgNumAndTypeOfAnchors; 167 } 168 169 SwObjectFormatter* SwObjectFormatter::CreateObjFormatter( 170 SwFrm& _rAnchorFrm, 171 const SwPageFrm& _rPageFrm, 172 SwLayAction* _pLayAction ) 173 { 174 SwObjectFormatter* pObjFormatter = 0L; 175 if ( _rAnchorFrm.IsTxtFrm() ) 176 { 177 pObjFormatter = SwObjectFormatterTxtFrm::CreateObjFormatter( 178 static_cast<SwTxtFrm&>(_rAnchorFrm), 179 _rPageFrm, _pLayAction ); 180 } 181 else if ( _rAnchorFrm.IsLayoutFrm() ) 182 { 183 pObjFormatter = SwObjectFormatterLayFrm::CreateObjFormatter( 184 static_cast<SwLayoutFrm&>(_rAnchorFrm), 185 _rPageFrm, _pLayAction ); 186 } 187 else 188 { 189 ASSERT( false, 190 "<SwObjectFormatter::CreateObjFormatter(..)> - unexcepted type of anchor frame" ); 191 } 192 193 return pObjFormatter; 194 } 195 196 /** method to format all floating screen objects at the given anchor frame 197 198 @author OD 199 */ 200 bool SwObjectFormatter::FormatObjsAtFrm( SwFrm& _rAnchorFrm, 201 const SwPageFrm& _rPageFrm, 202 SwLayAction* _pLayAction ) 203 { 204 bool bSuccess( true ); 205 206 // create corresponding object formatter 207 SwObjectFormatter* pObjFormatter = 208 SwObjectFormatter::CreateObjFormatter( _rAnchorFrm, _rPageFrm, _pLayAction ); 209 210 if ( pObjFormatter ) 211 { 212 // format anchored floating screen objects 213 bSuccess = pObjFormatter->DoFormatObjs(); 214 } 215 delete pObjFormatter; 216 217 return bSuccess; 218 } 219 220 /** method to format a given floating screen object 221 222 @author OD 223 */ 224 bool SwObjectFormatter::FormatObj( SwAnchoredObject& _rAnchoredObj, 225 SwFrm* _pAnchorFrm, 226 const SwPageFrm* _pPageFrm, 227 SwLayAction* _pLayAction ) 228 { 229 bool bSuccess( true ); 230 231 ASSERT( _pAnchorFrm || _rAnchoredObj.GetAnchorFrm(), 232 "<SwObjectFormatter::FormatObj(..)> - missing anchor frame" ); 233 SwFrm& rAnchorFrm = _pAnchorFrm ? *(_pAnchorFrm) : *(_rAnchoredObj.AnchorFrm()); 234 235 ASSERT( _pPageFrm || rAnchorFrm.FindPageFrm(), 236 "<SwObjectFormatter::FormatObj(..)> - missing page frame" ); 237 const SwPageFrm& rPageFrm = _pPageFrm ? *(_pPageFrm) : *(rAnchorFrm.FindPageFrm()); 238 239 // create corresponding object formatter 240 SwObjectFormatter* pObjFormatter = 241 SwObjectFormatter::CreateObjFormatter( rAnchorFrm, rPageFrm, _pLayAction ); 242 243 if ( pObjFormatter ) 244 { 245 // format given floating screen object 246 // --> OD 2005-01-10 #i40147# - check for moved forward anchor frame 247 bSuccess = pObjFormatter->DoFormatObj( _rAnchoredObj, true ); 248 // <-- 249 } 250 delete pObjFormatter; 251 252 return bSuccess; 253 } 254 255 /** helper method for method <_FormatObj(..)> - performs the intrinsic format 256 of the layout of the given layout frame and all its lower layout frames. 257 258 OD 2004-06-28 #i28701# 259 IMPORTANT NOTE: 260 Method corresponds to methods <SwLayAction::FormatLayoutFly(..)> and 261 <SwLayAction::FormatLayout(..)>. Thus, its code for the formatting have 262 to be synchronised. 263 264 @author OD 265 */ 266 void SwObjectFormatter::_FormatLayout( SwLayoutFrm& _rLayoutFrm ) 267 { 268 _rLayoutFrm.Calc(); 269 270 SwFrm* pLowerFrm = _rLayoutFrm.Lower(); 271 while ( pLowerFrm ) 272 { 273 if ( pLowerFrm->IsLayoutFrm() ) 274 { 275 _FormatLayout( *(static_cast<SwLayoutFrm*>(pLowerFrm)) ); 276 } 277 pLowerFrm = pLowerFrm->GetNext(); 278 } 279 } 280 281 /** helper method for method <_FormatObj(..)> - performs the intrinsic 282 format of the content of the given floating screen object. 283 284 OD 2004-06-28 #i28701# 285 286 @author OD 287 */ 288 void SwObjectFormatter::_FormatObjCntnt( SwAnchoredObject& _rAnchoredObj ) 289 { 290 if ( !_rAnchoredObj.ISA(SwFlyFrm) ) 291 { 292 // only Writer fly frames have content 293 return; 294 } 295 296 SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj); 297 SwCntntFrm* pCntnt = rFlyFrm.ContainsCntnt(); 298 299 while ( pCntnt ) 300 { 301 // format content 302 pCntnt->OptCalc(); 303 304 // format floating screen objects at content text frame 305 // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame to 306 // the object formatter 307 if ( pCntnt->IsTxtFrm() && 308 !SwObjectFormatter::FormatObjsAtFrm( *pCntnt, 309 *(pCntnt->FindPageFrm()), 310 GetLayAction() ) ) 311 // <-- 312 { 313 // restart format with first content 314 pCntnt = rFlyFrm.ContainsCntnt(); 315 continue; 316 } 317 318 // continue with next content 319 pCntnt = pCntnt->GetNextCntntFrm(); 320 } 321 } 322 323 /** performs the intrinsic format of a given floating screen object and its content. 324 325 OD 2004-06-28 #i28701# 326 327 @author OD 328 */ 329 void SwObjectFormatter::_FormatObj( SwAnchoredObject& _rAnchoredObj ) 330 { 331 // check, if only as-character anchored object have to be formatted, and 332 // check the anchor type 333 if ( FormatOnlyAsCharAnchored() && 334 !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) ) 335 { 336 return; 337 } 338 339 // collect anchor object and its 'anchor' page number, if requested 340 if ( mpPgNumAndTypeOfAnchors ) 341 { 342 mpPgNumAndTypeOfAnchors->Collect( _rAnchoredObj ); 343 } 344 345 if ( _rAnchoredObj.ISA(SwFlyFrm) ) 346 { 347 SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj); 348 // --> OD 2004-11-15 #i34753# - reset flag, which prevents a positioning 349 if ( rFlyFrm.IsFlyLayFrm() ) 350 { 351 static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( false ); 352 } 353 // <-- 354 355 // FME 2007-08-30 #i81146# new loop control 356 sal_uInt16 nLoopControlRuns = 0; 357 const sal_uInt16 nLoopControlMax = 15; 358 359 do { 360 if ( mpLayAction ) 361 { 362 mpLayAction->FormatLayoutFly( &rFlyFrm ); 363 // --> OD 2005-07-13 #124218# - consider, if the layout action 364 // has to be restarted due to a delete of a page frame. 365 if ( mpLayAction->IsAgain() ) 366 { 367 break; 368 } 369 // <-- 370 } 371 else 372 { 373 _FormatLayout( rFlyFrm ); 374 } 375 // --> OD 2004-11-15 #i34753# - prevent further positioning, if 376 // to-page|to-fly anchored Writer fly frame is already clipped. 377 if ( rFlyFrm.IsFlyLayFrm() && rFlyFrm.IsClipped() ) 378 { 379 static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( true ); 380 } 381 // <-- 382 // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame 383 // to the object formatter 384 SwObjectFormatter::FormatObjsAtFrm( rFlyFrm, 385 *(rFlyFrm.FindPageFrm()), 386 mpLayAction ); 387 // <-- 388 if ( mpLayAction ) 389 { 390 mpLayAction->_FormatFlyCntnt( &rFlyFrm ); 391 // --> OD 2005-07-13 #124218# - consider, if the layout action 392 // has to be restarted due to a delete of a page frame. 393 if ( mpLayAction->IsAgain() ) 394 { 395 break; 396 } 397 // <-- 398 } 399 else 400 { 401 _FormatObjCntnt( rFlyFrm ); 402 } 403 404 if ( ++nLoopControlRuns >= nLoopControlMax ) 405 { 406 #if OSL_DEBUG_LEVEL > 1 407 ASSERT( false, "LoopControl in SwObjectFormatter::_FormatObj: Stage 3!!!" ); 408 #endif 409 rFlyFrm.ValidateThisAndAllLowers( 2 ); 410 nLoopControlRuns = 0; 411 } 412 413 // --> OD 2006-02-02 #i57917# 414 // stop formatting of anchored object, if restart of layout process is requested. 415 } while ( !rFlyFrm.IsValid() && 416 !_rAnchoredObj.RestartLayoutProcess() && 417 rFlyFrm.GetAnchorFrm() == &GetAnchorFrm() ); 418 // <-- 419 } 420 else if ( _rAnchoredObj.ISA(SwAnchoredDrawObject) ) 421 { 422 _rAnchoredObj.MakeObjPos(); 423 } 424 } 425 426 /** invokes the intrinsic format method for all floating screen objects, 427 anchored at anchor frame on the given page frame 428 429 OD 2004-06-28 #i28701# 430 OD 2004-10-08 #i26945# - for format of floating screen objects for 431 follow text frames, the 'master' text frame is passed to the method. 432 Thus, the objects, whose anchor character is inside the follow text 433 frame can be formatted. 434 435 @author OD 436 */ 437 bool SwObjectFormatter::_FormatObjsAtFrm( SwTxtFrm* _pMasterTxtFrm ) 438 { 439 // --> OD 2004-10-08 #i26945# 440 SwFrm* pAnchorFrm( 0L ); 441 if ( GetAnchorFrm().IsTxtFrm() && 442 static_cast<SwTxtFrm&>(GetAnchorFrm()).IsFollow() && 443 _pMasterTxtFrm ) 444 { 445 pAnchorFrm = _pMasterTxtFrm; 446 } 447 else 448 { 449 pAnchorFrm = &GetAnchorFrm(); 450 } 451 // <-- 452 if ( !pAnchorFrm->GetDrawObjs() ) 453 { 454 // nothing to do, if no floating screen object is registered at the anchor frame. 455 return true; 456 } 457 458 bool bSuccess( true ); 459 460 sal_uInt32 i = 0; 461 for ( ; i < pAnchorFrm->GetDrawObjs()->Count(); ++i ) 462 { 463 SwAnchoredObject* pAnchoredObj = (*pAnchorFrm->GetDrawObjs())[i]; 464 465 // check, if object's anchor is on the given page frame or 466 // object is registered at the given page frame. 467 // --> OD 2004-10-05 #i26945# - check, if the anchor character of the 468 // anchored object is located in a follow text frame. If this anchor 469 // follow text frame differs from the given anchor frame, the given 470 // anchor frame is a 'master' text frame of the anchor follow text frame. 471 // If the anchor follow text frame is in the same body as its 'master' 472 // text frame, do not format the anchored object. 473 // E.g., this situation can occur during the table row splitting algorithm. 474 SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm(); 475 const bool bAnchoredAtFollowInSameBodyAsMaster = 476 pAnchorCharFrm && pAnchorCharFrm->IsFollow() && 477 pAnchorCharFrm != pAnchoredObj->GetAnchorFrm() && 478 pAnchorCharFrm->FindBodyFrm() == 479 static_cast<SwTxtFrm*>(pAnchoredObj->AnchorFrm())->FindBodyFrm(); 480 if ( bAnchoredAtFollowInSameBodyAsMaster ) 481 { 482 continue; 483 } 484 // <-- 485 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()> 486 // is replaced by method <FindPageFrmOfAnchor()>. It's return value 487 // have to be checked. 488 SwPageFrm* pPageFrmOfAnchor = pAnchoredObj->FindPageFrmOfAnchor(); 489 ASSERT( pPageFrmOfAnchor, 490 "<SwObjectFormatter::_FormatObjsAtFrm()> - missing page frame." ); 491 // --> OD 2004-10-08 #i26945# 492 if ( pPageFrmOfAnchor && pPageFrmOfAnchor == &mrPageFrm ) 493 // <-- 494 { 495 // if format of object fails, stop formatting and pass fail to 496 // calling method via the return value. 497 if ( !DoFormatObj( *pAnchoredObj ) ) 498 { 499 bSuccess = false; 500 break; 501 } 502 503 // considering changes at <pAnchorFrm->GetDrawObjs()> during 504 // format of the object. 505 if ( !pAnchorFrm->GetDrawObjs() || 506 i > pAnchorFrm->GetDrawObjs()->Count() ) 507 { 508 break; 509 } 510 else 511 { 512 sal_uInt32 nActPosOfObj = 513 pAnchorFrm->GetDrawObjs()->ListPosOf( *pAnchoredObj ); 514 if ( nActPosOfObj == pAnchorFrm->GetDrawObjs()->Count() || 515 nActPosOfObj > i ) 516 { 517 --i; 518 } 519 else if ( nActPosOfObj < i ) 520 { 521 i = nActPosOfObj; 522 } 523 } 524 } 525 } // end of loop on <pAnchorFrm->.GetDrawObjs()> 526 527 return bSuccess; 528 } 529 530 /** accessor to collected anchored object 531 532 OD 2004-07-05 #i28701# 533 534 @author OD 535 */ 536 SwAnchoredObject* SwObjectFormatter::GetCollectedObj( const sal_uInt32 _nIndex ) 537 { 538 return mpPgNumAndTypeOfAnchors ? (*mpPgNumAndTypeOfAnchors)[_nIndex] : 0L; 539 } 540 541 /** accessor to 'anchor' page number of collected anchored object 542 543 OD 2004-07-05 #i28701# 544 545 @author OD 546 */ 547 sal_uInt32 SwObjectFormatter::GetPgNumOfCollected( const sal_uInt32 _nIndex ) 548 { 549 return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->GetPageNum(_nIndex) : 0L; 550 } 551 552 /** accessor to 'anchor' type of collected anchored object 553 554 OD 2004-10-04 #i26945# 555 556 @author OD 557 */ 558 bool SwObjectFormatter::IsCollectedAnchoredAtMaster( const sal_uInt32 _nIndex ) 559 { 560 return mpPgNumAndTypeOfAnchors 561 ? mpPgNumAndTypeOfAnchors->AnchoredAtMaster(_nIndex) 562 : true; 563 } 564 565 /** accessor to total number of collected anchored objects 566 567 OD 2004-07-05 #i28701# 568 569 @author OD 570 */ 571 sal_uInt32 SwObjectFormatter::CountOfCollected() 572 { 573 return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->Count() : 0L; 574 } 575