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