1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_slideshow.hxx" 30 31 #include <canvas/debug.hxx> 32 #include <tools/diagnose_ex.h> 33 #include <basegfx/range/b1drange.hxx> 34 #include <basegfx/matrix/b2dhommatrix.hxx> 35 36 #include <comphelper/anytostring.hxx> 37 #include <cppuhelper/exc_hlp.hxx> 38 39 #include <boost/bind.hpp> 40 #include <algorithm> 41 42 #include "layermanager.hxx" 43 44 using namespace ::com::sun::star; 45 46 namespace boost 47 { 48 // add operator!= for weak_ptr 49 inline bool operator!=( slideshow::internal::LayerWeakPtr const& rLHS, 50 slideshow::internal::LayerWeakPtr const& rRHS ) 51 { 52 return (rLHS<rRHS) || (rRHS<rLHS); 53 } 54 } 55 56 namespace slideshow 57 { 58 namespace internal 59 { 60 template<typename LayerFunc, 61 typename ShapeFunc> void LayerManager::manageViews( 62 LayerFunc layerFunc, 63 ShapeFunc shapeFunc ) 64 { 65 LayerSharedPtr pCurrLayer; 66 ViewLayerSharedPtr pCurrViewLayer; 67 LayerShapeMap::const_iterator aIter( maAllShapes.begin() ); 68 const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() ); 69 while( aIter != aEnd ) 70 { 71 LayerSharedPtr pLayer = aIter->second.lock(); 72 if( pLayer && pLayer != pCurrLayer ) 73 { 74 pCurrLayer = pLayer; 75 pCurrViewLayer = layerFunc(pCurrLayer); 76 } 77 78 if( pCurrViewLayer ) 79 shapeFunc(aIter->first,pCurrViewLayer); 80 81 ++aIter; 82 } 83 } 84 85 LayerManager::LayerManager( const UnoViewContainer& rViews, 86 const ::basegfx::B2DRange& rPageBounds, 87 bool bDisableAnimationZOrder ) : 88 mrViews(rViews), 89 maLayers(), 90 maXShapeHash( 101 ), 91 maAllShapes(), 92 maUpdateShapes(), 93 maPageBounds( rPageBounds ), 94 mnActiveSprites(0), 95 mbLayerAssociationDirty(false), 96 mbActive(false), 97 mbDisableAnimationZOrder(bDisableAnimationZOrder) 98 { 99 // prevent frequent resizes (won't have more than 4 layers 100 // for 99.9% of the cases) 101 maLayers.reserve(4); 102 103 // create initial background layer 104 maLayers.push_back( 105 Layer::createBackgroundLayer( 106 maPageBounds )); 107 108 // init views 109 std::for_each( mrViews.begin(), 110 mrViews.end(), 111 ::boost::bind(&LayerManager::viewAdded, 112 this, 113 _1) ); 114 } 115 116 void LayerManager::activate( bool bSlideBackgoundPainted ) 117 { 118 mbActive = true; 119 maUpdateShapes.clear(); // update gets forced via area, or 120 // has happend outside already 121 122 if( !bSlideBackgoundPainted ) 123 { 124 std::for_each(mrViews.begin(), 125 mrViews.end(), 126 boost::mem_fn(&View::clearAll)); 127 128 // force update of whole slide area 129 std::for_each( maLayers.begin(), 130 maLayers.end(), 131 boost::bind( &Layer::addUpdateRange, 132 _1, 133 boost::cref(maPageBounds) )); 134 } 135 else 136 { 137 // clear all possibly pending update areas - content 138 // is there, already 139 std::for_each( maLayers.begin(), 140 maLayers.end(), 141 boost::mem_fn( &Layer::clearUpdateRanges )); 142 } 143 144 updateShapeLayers( bSlideBackgoundPainted ); 145 } 146 147 void LayerManager::deactivate() 148 { 149 // TODO(F3): This is mostly a hack. Problem is, there's 150 // currently no smart way of telling shapes "remove your 151 // sprites". Others, like MediaShapes, listen to 152 // start/stop animation events, which is too much overhead 153 // for all shapes, though. 154 155 const bool bMoreThanOneLayer(maLayers.size() > 1); 156 if( mnActiveSprites || bMoreThanOneLayer ) 157 { 158 // clear all viewlayers, dump everything but the 159 // background layer - this will also remove all shape 160 // sprites 161 std::for_each(maAllShapes.begin(), 162 maAllShapes.end(), 163 boost::bind( &Shape::clearAllViewLayers, 164 boost::bind( std::select1st<LayerShapeMap::value_type>(), 165 _1 ))); 166 167 for (LayerShapeMap::iterator 168 iShape (maAllShapes.begin()), 169 iEnd (maAllShapes.end()); 170 iShape!=iEnd; 171 ++iShape) 172 { 173 iShape->second.reset(); 174 } 175 176 if( bMoreThanOneLayer ) 177 maLayers.erase(maLayers.begin()+1, 178 maLayers.end()); 179 180 mbLayerAssociationDirty = true; 181 } 182 183 mbActive = false; 184 185 // only background layer left 186 OSL_ASSERT( maLayers.size() == 1 && maLayers.front()->isBackgroundLayer() ); 187 } 188 189 void LayerManager::viewAdded( const UnoViewSharedPtr& rView ) 190 { 191 // view must be member of mrViews container 192 OSL_ASSERT( std::find(mrViews.begin(), 193 mrViews.end(), 194 rView) != mrViews.end() ); 195 196 // init view content 197 if( mbActive ) 198 rView->clearAll(); 199 200 // add View to all registered shapes 201 manageViews( 202 boost::bind(&Layer::addView, 203 _1, 204 boost::cref(rView)), 205 // repaint on view add 206 boost::bind(&Shape::addViewLayer, 207 _1, 208 _2, 209 true) ); 210 211 // in case we haven't reached all layers from the 212 // maAllShapes, issue addView again for good measure 213 std::for_each( maLayers.begin(), 214 maLayers.end(), 215 boost::bind( &Layer::addView, 216 _1, 217 boost::cref(rView) )); 218 } 219 220 void LayerManager::viewRemoved( const UnoViewSharedPtr& rView ) 221 { 222 // view must not be member of mrViews container anymore 223 OSL_ASSERT( std::find(mrViews.begin(), 224 mrViews.end(), 225 rView) == mrViews.end() ); 226 227 // remove View from all registered shapes 228 manageViews( 229 boost::bind(&Layer::removeView, 230 _1, 231 boost::cref(rView)), 232 boost::bind(&Shape::removeViewLayer, 233 _1, 234 _2) ); 235 236 // in case we haven't reached all layers from the 237 // maAllShapes, issue removeView again for good measure 238 std::for_each( maLayers.begin(), 239 maLayers.end(), 240 boost::bind( &Layer::removeView, 241 _1, 242 boost::cref(rView) )); 243 } 244 245 void LayerManager::viewChanged( const UnoViewSharedPtr& rView ) 246 { 247 (void)rView; 248 249 // view must be member of mrViews container 250 OSL_ASSERT( std::find(mrViews.begin(), 251 mrViews.end(), 252 rView) != mrViews.end() ); 253 254 // TODO(P2): selectively update only changed view 255 viewsChanged(); 256 } 257 258 void LayerManager::viewsChanged() 259 { 260 if( !mbActive ) 261 return; 262 263 // clear view area 264 ::std::for_each( mrViews.begin(), 265 mrViews.end(), 266 ::boost::mem_fn(&View::clearAll) ); 267 268 // TODO(F3): resize and repaint all layers 269 270 // render all shapes 271 std::for_each( maAllShapes.begin(), 272 maAllShapes.end(), 273 boost::bind(&Shape::render, 274 boost::bind( ::std::select1st<LayerShapeMap::value_type>(), _1)) ); 275 } 276 277 void LayerManager::addShape( const ShapeSharedPtr& rShape ) 278 { 279 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 280 ENSURE_OR_THROW( rShape, "LayerManager::addShape(): invalid Shape" ); 281 282 // add shape to XShape hash map 283 if( !maXShapeHash.insert( 284 XShapeHash::value_type( rShape->getXShape(), 285 rShape) ).second ) 286 { 287 // entry already present, nothing to do 288 return; 289 } 290 291 // add shape to appropriate layer 292 implAddShape( rShape ); 293 } 294 295 void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type& rShapeEntry ) 296 { 297 LayerSharedPtr& rBgLayer( maLayers.front() ); 298 rBgLayer->setShapeViews(rShapeEntry.first); 299 rShapeEntry.second = rBgLayer; 300 } 301 302 void LayerManager::implAddShape( const ShapeSharedPtr& rShape ) 303 { 304 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 305 ENSURE_OR_THROW( rShape, "LayerManager::implAddShape(): invalid Shape" ); 306 307 LayerShapeMap::value_type aValue (rShape, LayerWeakPtr()); 308 309 OSL_ASSERT( maAllShapes.find(rShape) == maAllShapes.end() ); // shape must not be added already 310 mbLayerAssociationDirty = true; 311 312 if( mbDisableAnimationZOrder ) 313 putShape2BackgroundLayer( 314 *maAllShapes.insert(aValue).first ); 315 else 316 maAllShapes.insert(aValue); 317 318 // update shape, it's just added and not yet painted 319 if( rShape->isVisible() ) 320 notifyShapeUpdate( rShape ); 321 } 322 323 bool LayerManager::removeShape( const ShapeSharedPtr& rShape ) 324 { 325 // remove shape from XShape hash map 326 if( maXShapeHash.erase( rShape->getXShape() ) == 0 ) 327 return false; // shape not in map 328 329 OSL_ASSERT( maAllShapes.find(rShape) != maAllShapes.end() ); 330 331 implRemoveShape( rShape ); 332 333 return true; 334 } 335 336 void LayerManager::implRemoveShape( const ShapeSharedPtr& rShape ) 337 { 338 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 339 ENSURE_OR_THROW( rShape, "LayerManager::implRemoveShape(): invalid Shape" ); 340 341 const LayerShapeMap::iterator aShapeEntry( maAllShapes.find(rShape) ); 342 343 if( aShapeEntry == maAllShapes.end() ) 344 return; 345 346 const bool bShapeUpdateNotified = maUpdateShapes.erase( rShape ) != 0; 347 348 // Enter shape area to the update area, but only if shape 349 // is visible and not in sprite mode (otherwise, updating 350 // the area doesn't do actual harm, but costs time) 351 // Actually, also add it if it was listed in 352 // maUpdateShapes (might have just gone invisible). 353 if( bShapeUpdateNotified || 354 (rShape->isVisible() && 355 !rShape->isBackgroundDetached()) ) 356 { 357 LayerSharedPtr pLayer = aShapeEntry->second.lock(); 358 if( pLayer ) 359 { 360 // store area early, once the shape is removed from 361 // the layers, it no longer has any view references 362 pLayer->addUpdateRange( rShape->getUpdateArea() ); 363 } 364 } 365 366 rShape->clearAllViewLayers(); 367 maAllShapes.erase( aShapeEntry ); 368 369 mbLayerAssociationDirty = true; 370 } 371 372 ShapeSharedPtr LayerManager::lookupShape( const uno::Reference< drawing::XShape >& xShape ) const 373 { 374 ENSURE_OR_THROW( xShape.is(), "LayerManager::lookupShape(): invalid Shape" ); 375 376 const XShapeHash::const_iterator aIter( maXShapeHash.find( xShape )); 377 if( aIter == maXShapeHash.end() ) 378 return ShapeSharedPtr(); // not found 379 380 // found, return data part of entry pair. 381 return aIter->second; 382 } 383 384 AttributableShapeSharedPtr LayerManager::getSubsetShape( const AttributableShapeSharedPtr& rOrigShape, 385 const DocTreeNode& rTreeNode ) 386 { 387 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 388 389 AttributableShapeSharedPtr pSubset; 390 391 // shape already added? 392 if( rOrigShape->createSubset( pSubset, 393 rTreeNode ) ) 394 { 395 OSL_ENSURE( pSubset, "LayerManager::getSubsetShape(): failed to create subset" ); 396 397 // don't add to shape hash, we're dupes to the 398 // original XShape anyway - all subset shapes return 399 // the same XShape as the original one. 400 401 // add shape to corresponding layer 402 implAddShape( pSubset ); 403 404 // update original shape, it now shows less content 405 // (the subset is removed from its displayed 406 // output). Subset shape is updated within 407 // implAddShape(). 408 if( rOrigShape->isVisible() ) 409 notifyShapeUpdate( rOrigShape ); 410 } 411 412 return pSubset; 413 } 414 415 void LayerManager::revokeSubset( const AttributableShapeSharedPtr& rOrigShape, 416 const AttributableShapeSharedPtr& rSubsetShape ) 417 { 418 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 419 420 if( rOrigShape->revokeSubset( rSubsetShape ) ) 421 { 422 OSL_ASSERT( maAllShapes.find(rSubsetShape) != maAllShapes.end() ); 423 424 implRemoveShape( rSubsetShape ); 425 426 // update original shape, it now shows more content 427 // (the subset is added back to its displayed output) 428 if( rOrigShape->isVisible() ) 429 notifyShapeUpdate( rOrigShape ); 430 } 431 } 432 433 void LayerManager::enterAnimationMode( const AnimatableShapeSharedPtr& rShape ) 434 { 435 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 436 ENSURE_OR_THROW( rShape, "LayerManager::enterAnimationMode(): invalid Shape" ); 437 438 const bool bPrevAnimState( rShape->isBackgroundDetached() ); 439 440 rShape->enterAnimationMode(); 441 442 // if this call _really_ enabled the animation mode at 443 // rShape, insert it to our enter animation queue, to 444 // perform the necessary layer reorg lazily on 445 // LayerManager::update()/render(). 446 if( bPrevAnimState != rShape->isBackgroundDetached() ) 447 { 448 ++mnActiveSprites; 449 mbLayerAssociationDirty = true; 450 451 // area needs update (shape is removed from normal 452 // slide, and now rendered as an autonomous 453 // sprite). store in update set 454 if( rShape->isVisible() ) 455 addUpdateArea( rShape ); 456 } 457 458 // TODO(P1): this can lead to potential wasted effort, if 459 // a shape gets toggled animated/unanimated a few times 460 // between two frames, returning to the original state. 461 } 462 463 void LayerManager::leaveAnimationMode( const AnimatableShapeSharedPtr& rShape ) 464 { 465 ENSURE_OR_THROW( !maLayers.empty(), "LayerManager::leaveAnimationMode(): no layers" ); 466 ENSURE_OR_THROW( rShape, "LayerManager::leaveAnimationMode(): invalid Shape" ); 467 468 const bool bPrevAnimState( rShape->isBackgroundDetached() ); 469 470 rShape->leaveAnimationMode(); 471 472 // if this call _really_ ended the animation mode at 473 // rShape, insert it to our leave animation queue, to 474 // perform the necessary layer reorg lazily on 475 // LayerManager::update()/render(). 476 if( bPrevAnimState != rShape->isBackgroundDetached() ) 477 { 478 --mnActiveSprites; 479 mbLayerAssociationDirty = true; 480 481 // shape needs update, no previous rendering, fast 482 // update possible. 483 if( rShape->isVisible() ) 484 notifyShapeUpdate( rShape ); 485 } 486 487 // TODO(P1): this can lead to potential wasted effort, if 488 // a shape gets toggled animated/unanimated a few times 489 // between two frames, returning to the original state. 490 } 491 492 void LayerManager::notifyShapeUpdate( const ShapeSharedPtr& rShape ) 493 { 494 if( !mbActive || mrViews.empty() ) 495 return; 496 497 // hidden sprite-shape needs render() call still, to hide sprite 498 if( rShape->isVisible() || rShape->isBackgroundDetached() ) 499 maUpdateShapes.insert( rShape ); 500 else 501 addUpdateArea( rShape ); 502 } 503 504 bool LayerManager::isUpdatePending() const 505 { 506 if( !mbActive ) 507 return false; 508 509 if( mbLayerAssociationDirty || !maUpdateShapes.empty() ) 510 return true; 511 512 const LayerVector::const_iterator aEnd( maLayers.end() ); 513 if( std::find_if( maLayers.begin(), 514 aEnd, 515 boost::mem_fn(&Layer::isUpdatePending)) != aEnd ) 516 return true; 517 518 return false; 519 } 520 521 bool LayerManager::updateSprites() 522 { 523 bool bRet(true); 524 525 // send update() calls to every shape in the 526 // maUpdateShapes set, which is _animated_ (i.e. a 527 // sprite). 528 const ShapeUpdateSet::const_iterator aEnd=maUpdateShapes.end(); 529 ShapeUpdateSet::const_iterator aCurrShape=maUpdateShapes.begin(); 530 while( aCurrShape != aEnd ) 531 { 532 if( (*aCurrShape)->isBackgroundDetached() ) 533 { 534 // can update shape directly, without 535 // affecting layer content (shape is 536 // currently displayed in a sprite) 537 if( !(*aCurrShape)->update() ) 538 bRet = false; // delay error exit 539 } 540 else 541 { 542 // TODO(P2): addUpdateArea() involves log(n) 543 // search for shape layer. Have a frequent 544 // shape/layer association cache, or ptr back to 545 // layer at the shape? 546 547 // cannot update shape directly, it's not 548 // animated and update() calls will prolly 549 // overwrite other page content. 550 addUpdateArea( *aCurrShape ); 551 } 552 553 ++aCurrShape; 554 } 555 556 maUpdateShapes.clear(); 557 558 return bRet; 559 } 560 561 bool LayerManager::update() 562 { 563 bool bRet = true; 564 565 if( !mbActive ) 566 return bRet; 567 568 // going to render - better flush any pending layer reorg 569 // now 570 updateShapeLayers(false); 571 572 // all sprites 573 bRet = updateSprites(); 574 575 // any non-sprite update areas left? 576 if( std::find_if( maLayers.begin(), 577 maLayers.end(), 578 boost::mem_fn( &Layer::isUpdatePending )) == maLayers.end() ) 579 return bRet; // nope, done. 580 581 // update each shape on each layer, that has 582 // isUpdatePending() 583 bool bIsCurrLayerUpdating(false); 584 Layer::EndUpdater aEndUpdater; 585 LayerSharedPtr pCurrLayer; 586 LayerShapeMap::const_iterator aIter( maAllShapes.begin() ); 587 const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() ); 588 while( aIter != aEnd ) 589 { 590 LayerSharedPtr pLayer = aIter->second.lock(); 591 if( pLayer != pCurrLayer ) 592 { 593 pCurrLayer = pLayer; 594 bIsCurrLayerUpdating = pCurrLayer->isUpdatePending(); 595 596 if( bIsCurrLayerUpdating ) 597 aEndUpdater = pCurrLayer->beginUpdate(); 598 } 599 600 if( bIsCurrLayerUpdating && 601 !aIter->first->isBackgroundDetached() && 602 pCurrLayer->isInsideUpdateArea(aIter->first) ) 603 { 604 if( !aIter->first->render() ) 605 bRet = false; 606 } 607 608 ++aIter; 609 } 610 611 return bRet; 612 } 613 614 namespace 615 { 616 /** Little wrapper around a Canvas, to render one-shot 617 into a canvas 618 */ 619 class DummyLayer : public ViewLayer 620 { 621 public: 622 explicit DummyLayer( const ::cppcanvas::CanvasSharedPtr& rCanvas ) : 623 mpCanvas( rCanvas ) 624 { 625 } 626 627 virtual bool isOnView(boost::shared_ptr<View> const& /*rView*/) const 628 { 629 return true; // visible on all views 630 } 631 632 virtual ::cppcanvas::CanvasSharedPtr getCanvas() const 633 { 634 return mpCanvas; 635 } 636 637 virtual void clear() const 638 { 639 // NOOP 640 } 641 642 virtual void clearAll() const 643 { 644 // NOOP 645 } 646 647 virtual ::cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& /*rSpriteSizePixel*/, 648 double /*nSpritePrio*/ ) const 649 { 650 ENSURE_OR_THROW( false, 651 "DummyLayer::createSprite(): This method is not supposed to be called!" ); 652 return ::cppcanvas::CustomSpriteSharedPtr(); 653 } 654 655 virtual void setPriority( const basegfx::B1DRange& /*rRange*/ ) 656 { 657 OSL_ENSURE( false, 658 "BitmapView::setPriority(): This method is not supposed to be called!" ); 659 } 660 661 virtual ::basegfx::B2DHomMatrix getTransformation() const 662 { 663 return mpCanvas->getTransformation(); 664 } 665 666 virtual ::basegfx::B2DHomMatrix getSpriteTransformation() const 667 { 668 OSL_ENSURE( false, 669 "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" ); 670 return ::basegfx::B2DHomMatrix(); 671 } 672 673 virtual void setClip( const ::basegfx::B2DPolyPolygon& /*rClip*/ ) 674 { 675 OSL_ENSURE( false, 676 "BitmapView::setClip(): This method is not supposed to be called!" ); 677 } 678 679 virtual bool resize( const ::basegfx::B2DRange& /*rArea*/ ) 680 { 681 OSL_ENSURE( false, 682 "BitmapView::resize(): This method is not supposed to be called!" ); 683 return false; 684 } 685 686 private: 687 ::cppcanvas::CanvasSharedPtr mpCanvas; 688 }; 689 } 690 691 bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr& rTargetCanvas ) const 692 { 693 bool bRet( true ); 694 ViewLayerSharedPtr pTmpLayer( new DummyLayer( rTargetCanvas ) ); 695 696 LayerShapeMap::const_iterator aIter( maAllShapes.begin() ); 697 const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() ); 698 while( aIter != aEnd ) 699 { 700 try 701 { 702 // forward to all shape's addViewLayer method (which 703 // we request to render the Shape on the new 704 // ViewLayer. Since we add the shapes in the 705 // maShapeSet order (which is also the render order), 706 // this is equivalent to a subsequent render() call) 707 aIter->first->addViewLayer( pTmpLayer, 708 true ); 709 710 // and remove again, this is only temporary 711 aIter->first->removeViewLayer( pTmpLayer ); 712 } 713 catch( uno::Exception& ) 714 { 715 // TODO(E1): Might be superfluous. Nowadays, 716 // addViewLayer swallows all errors, anyway. 717 OSL_ENSURE( false, 718 rtl::OUStringToOString( 719 comphelper::anyToString( cppu::getCaughtException() ), 720 RTL_TEXTENCODING_UTF8 ).getStr() ); 721 722 // at least one shape could not be rendered 723 bRet = false; 724 } 725 726 ++aIter; 727 } 728 729 return bRet; 730 } 731 732 void LayerManager::addUpdateArea( ShapeSharedPtr const& rShape ) 733 { 734 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 735 ENSURE_OR_THROW( rShape, "LayerManager::addUpdateArea(): invalid Shape" ); 736 737 const LayerShapeMap::const_iterator aShapeEntry( maAllShapes.find(rShape) ); 738 739 if( aShapeEntry == maAllShapes.end() ) 740 return; 741 742 LayerSharedPtr pLayer = aShapeEntry->second.lock(); 743 if( pLayer ) 744 pLayer->addUpdateRange( rShape->getUpdateArea() ); 745 } 746 747 void LayerManager::commitLayerChanges( std::size_t nCurrLayerIndex, 748 LayerShapeMap::const_iterator aFirstLayerShape, 749 LayerShapeMap::const_iterator aEndLayerShapes ) 750 { 751 const bool bLayerExists( maLayers.size() > nCurrLayerIndex ); 752 if( bLayerExists ) 753 { 754 const LayerSharedPtr& rLayer( maLayers.at(nCurrLayerIndex) ); 755 const bool bLayerResized( rLayer->commitBounds() ); 756 rLayer->setPriority( basegfx::B1DRange(nCurrLayerIndex, 757 nCurrLayerIndex+1) ); 758 759 if( bLayerResized ) 760 { 761 // need to re-render whole layer - start from 762 // clean state 763 rLayer->clearContent(); 764 765 // render and remove from update set 766 while( aFirstLayerShape != aEndLayerShapes ) 767 { 768 maUpdateShapes.erase(aFirstLayerShape->first); 769 aFirstLayerShape->first->render(); 770 ++aFirstLayerShape; 771 } 772 } 773 } 774 } 775 776 LayerSharedPtr LayerManager::createForegroundLayer() const 777 { 778 OSL_ASSERT( mbActive ); 779 780 LayerSharedPtr pLayer( Layer::createLayer( 781 maPageBounds )); 782 783 // create ViewLayers for all registered views, and add to 784 // newly created layer. 785 ::std::for_each( mrViews.begin(), 786 mrViews.end(), 787 boost::bind( &Layer::addView, 788 boost::cref(pLayer), 789 _1 )); 790 791 return pLayer; 792 } 793 794 void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted ) 795 { 796 OSL_ASSERT( !maLayers.empty() ); // always at least background layer 797 OSL_ASSERT( mbActive ); 798 799 // do we need to process shapes? 800 if( !mbLayerAssociationDirty ) 801 return; 802 803 if( mbDisableAnimationZOrder ) 804 { 805 // layer setup happened elsewhere, is only bg layer 806 // anyway. 807 mbLayerAssociationDirty = false; 808 return; 809 } 810 811 // scan through maAllShapes, and determine shape animation 812 // discontinuities: when a shape that has 813 // isBackgroundDetached() return false follows a shape 814 // with isBackgroundDetached() true, the former and all 815 // following ones must be moved into an own layer. 816 817 // to avoid tons of temporaries, create weak_ptr to Layers 818 // beforehand 819 std::vector< LayerWeakPtr > aWeakLayers(maLayers.size()); 820 std::copy(maLayers.begin(),maLayers.end(),aWeakLayers.begin()); 821 822 std::size_t nCurrLayerIndex(0); 823 bool bIsBackgroundLayer(true); 824 bool bLastWasBackgroundDetached(false); // last shape sprite state 825 LayerShapeMap::iterator aCurrShapeEntry( maAllShapes.begin() ); 826 LayerShapeMap::iterator aCurrLayerFirstShapeEntry( maAllShapes.begin() ); 827 const LayerShapeMap::iterator aEndShapeEntry ( maAllShapes.end() ); 828 ShapeUpdateSet aUpdatedShapes; // shapes that need update 829 while( aCurrShapeEntry != aEndShapeEntry ) 830 { 831 const ShapeSharedPtr pCurrShape( aCurrShapeEntry->first ); 832 const bool bThisIsBackgroundDetached( 833 pCurrShape->isBackgroundDetached() ); 834 835 if( bLastWasBackgroundDetached == true && 836 bThisIsBackgroundDetached == false ) 837 { 838 // discontinuity found - current shape needs to 839 // get into a new layer 840 // -------------------------------------------- 841 842 // commit changes to previous layer 843 commitLayerChanges(nCurrLayerIndex, 844 aCurrLayerFirstShapeEntry, 845 aCurrShapeEntry); 846 aCurrLayerFirstShapeEntry=aCurrShapeEntry; 847 ++nCurrLayerIndex; 848 bIsBackgroundLayer = false; 849 850 if( aWeakLayers.size() <= nCurrLayerIndex || 851 aWeakLayers.at(nCurrLayerIndex) != aCurrShapeEntry->second ) 852 { 853 // no more layers left, or shape was not 854 // member of this layer - create a new one 855 maLayers.insert( maLayers.begin()+nCurrLayerIndex, 856 createForegroundLayer() ); 857 aWeakLayers.insert( aWeakLayers.begin()+nCurrLayerIndex, 858 maLayers[nCurrLayerIndex] ); 859 } 860 } 861 862 OSL_ASSERT( maLayers.size() == aWeakLayers.size() ); 863 864 // note: using indices here, since vector::insert 865 // above invalidates iterators 866 LayerSharedPtr& rCurrLayer( maLayers.at(nCurrLayerIndex) ); 867 LayerWeakPtr& rCurrWeakLayer( aWeakLayers.at(nCurrLayerIndex) ); 868 if( rCurrWeakLayer != aCurrShapeEntry->second ) 869 { 870 // mismatch: shape is not contained in current 871 // layer - move shape to that layer, then. 872 maLayers.at(nCurrLayerIndex)->setShapeViews( 873 pCurrShape ); 874 875 // layer got new shape(s), need full repaint, if 876 // non-sprite shape 877 if( !bThisIsBackgroundDetached && pCurrShape->isVisible() ) 878 { 879 LayerSharedPtr pOldLayer( aCurrShapeEntry->second.lock() ); 880 if( pOldLayer ) 881 { 882 // old layer still valid? then we need to 883 // repaint former shape area 884 pOldLayer->addUpdateRange( 885 pCurrShape->getUpdateArea() ); 886 } 887 888 // render on new layer (only if not 889 // explicitely disabled) 890 if( !(bBackgroundLayerPainted && bIsBackgroundLayer) ) 891 maUpdateShapes.insert( pCurrShape ); 892 } 893 894 aCurrShapeEntry->second = rCurrWeakLayer; 895 } 896 897 // update layerbounds regardless of the fact that the 898 // shape might be contained in said layer 899 // already. updateBounds() is dumb and needs to 900 // collect all shape bounds. 901 // of course, no need to expand layer bounds for 902 // shapes that reside in sprites themselves. 903 if( !bThisIsBackgroundDetached && !bIsBackgroundLayer ) 904 rCurrLayer->updateBounds( pCurrShape ); 905 906 bLastWasBackgroundDetached = bThisIsBackgroundDetached; 907 ++aCurrShapeEntry; 908 } 909 910 // commit very last layer data 911 commitLayerChanges(nCurrLayerIndex, 912 aCurrLayerFirstShapeEntry, 913 aCurrShapeEntry); 914 915 // any layers left? Bin them! 916 if( maLayers.size() > nCurrLayerIndex+1 ) 917 maLayers.erase(maLayers.begin()+nCurrLayerIndex+1, 918 maLayers.end()); 919 920 mbLayerAssociationDirty = false; 921 } 922 } 923 } 924