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 // must be first
28cdf0e10cSrcweir #include <canvas/debug.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
31cdf0e10cSrcweir #include <basegfx/range/b1drange.hxx>
32cdf0e10cSrcweir #include <basegfx/range/b2dpolyrange.hxx>
33cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
34cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx>
35cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
36cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "layer.hxx"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <boost/bind.hpp>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir 
43cdf0e10cSrcweir using namespace ::com::sun::star;
44cdf0e10cSrcweir 
45cdf0e10cSrcweir namespace slideshow
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     namespace internal
48cdf0e10cSrcweir     {
Layer(const basegfx::B2DRange & rMaxLayerBounds,Dummy)49cdf0e10cSrcweir         Layer::Layer( const basegfx::B2DRange& rMaxLayerBounds,
50cdf0e10cSrcweir                       Dummy                     ) :
51cdf0e10cSrcweir             maViewEntries(),
52cdf0e10cSrcweir             maBounds(),
53cdf0e10cSrcweir             maNewBounds(),
54cdf0e10cSrcweir             maMaxBounds( rMaxLayerBounds ),
55cdf0e10cSrcweir             mbBoundsDirty(false),
56cdf0e10cSrcweir             mbBackgroundLayer(true),
57cdf0e10cSrcweir             mbClipSet(false)
58cdf0e10cSrcweir         {
59cdf0e10cSrcweir         }
60cdf0e10cSrcweir 
Layer(const basegfx::B2DRange & rMaxLayerBounds)61cdf0e10cSrcweir         Layer::Layer( const basegfx::B2DRange& rMaxLayerBounds ) :
62cdf0e10cSrcweir             maViewEntries(),
63cdf0e10cSrcweir             maBounds(),
64cdf0e10cSrcweir             maNewBounds(),
65cdf0e10cSrcweir             maMaxBounds( rMaxLayerBounds ),
66cdf0e10cSrcweir             mbBoundsDirty(false),
67cdf0e10cSrcweir             mbBackgroundLayer(false),
68cdf0e10cSrcweir             mbClipSet(false)
69cdf0e10cSrcweir         {
70cdf0e10cSrcweir         }
71cdf0e10cSrcweir 
addView(const ViewSharedPtr & rNewView)72cdf0e10cSrcweir         ViewLayerSharedPtr Layer::addView( const ViewSharedPtr& rNewView )
73cdf0e10cSrcweir         {
74cdf0e10cSrcweir             OSL_ASSERT( rNewView );
75cdf0e10cSrcweir 
76cdf0e10cSrcweir             ViewEntryVector::iterator aIter;
77cdf0e10cSrcweir             const ViewEntryVector::iterator aEnd( maViewEntries.end() );
78cdf0e10cSrcweir             if( (aIter=std::find_if( maViewEntries.begin(),
79cdf0e10cSrcweir                                      aEnd,
80cdf0e10cSrcweir                                      boost::bind<bool>(
81cdf0e10cSrcweir                                          std::equal_to< ViewSharedPtr >(),
82cdf0e10cSrcweir                                          boost::bind( &ViewEntry::getView, _1 ),
83cdf0e10cSrcweir                                          boost::cref( rNewView )))) != aEnd )
84cdf0e10cSrcweir             {
85cdf0e10cSrcweir                 // already added - just return existing layer
86cdf0e10cSrcweir                 return aIter->mpViewLayer;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir             }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir             // not yet added - create new view layer
91cdf0e10cSrcweir             ViewLayerSharedPtr pNewLayer;
92cdf0e10cSrcweir             if( mbBackgroundLayer )
93cdf0e10cSrcweir                 pNewLayer = rNewView;
94cdf0e10cSrcweir             else
95cdf0e10cSrcweir                 pNewLayer = rNewView->createViewLayer(maBounds);
96cdf0e10cSrcweir 
97cdf0e10cSrcweir             // add to local list
98cdf0e10cSrcweir             maViewEntries.push_back(
99cdf0e10cSrcweir                 ViewEntry( rNewView,
100cdf0e10cSrcweir                            pNewLayer ));
101cdf0e10cSrcweir 
102cdf0e10cSrcweir             return maViewEntries.back().mpViewLayer;
103cdf0e10cSrcweir         }
104cdf0e10cSrcweir 
removeView(const ViewSharedPtr & rView)105cdf0e10cSrcweir         ViewLayerSharedPtr Layer::removeView( const ViewSharedPtr& rView )
106cdf0e10cSrcweir         {
107cdf0e10cSrcweir             OSL_ASSERT( rView );
108cdf0e10cSrcweir 
109cdf0e10cSrcweir             ViewEntryVector::iterator       aIter;
110cdf0e10cSrcweir             const ViewEntryVector::iterator aEnd( maViewEntries.end() );
111cdf0e10cSrcweir             if( (aIter=std::find_if( maViewEntries.begin(),
112cdf0e10cSrcweir                                        aEnd,
113cdf0e10cSrcweir                                        boost::bind<bool>(
114cdf0e10cSrcweir                                            std::equal_to< ViewSharedPtr >(),
115cdf0e10cSrcweir                                            boost::bind( &ViewEntry::getView, _1 ),
116cdf0e10cSrcweir                                            boost::cref( rView )))) == aEnd )
117cdf0e10cSrcweir             {
118cdf0e10cSrcweir                 // View was not added/is already removed
119cdf0e10cSrcweir                 return ViewLayerSharedPtr();
120cdf0e10cSrcweir             }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir             OSL_ENSURE( std::count_if( maViewEntries.begin(),
123cdf0e10cSrcweir                                        aEnd,
124cdf0e10cSrcweir                                        boost::bind<bool>(
125cdf0e10cSrcweir                                            std::equal_to< ViewSharedPtr >(),
126cdf0e10cSrcweir                                            boost::bind( &ViewEntry::getView, _1 ),
127cdf0e10cSrcweir                                            boost::cref( rView ))) == 1,
128cdf0e10cSrcweir                         "Layer::removeView(): view added multiple times" );
129cdf0e10cSrcweir 
130cdf0e10cSrcweir             ViewLayerSharedPtr pRet( aIter->mpViewLayer );
131cdf0e10cSrcweir             maViewEntries.erase(aIter);
132cdf0e10cSrcweir 
133cdf0e10cSrcweir             return pRet;
134cdf0e10cSrcweir         }
135cdf0e10cSrcweir 
viewChanged(const ViewSharedPtr & rChangedView)136cdf0e10cSrcweir         void Layer::viewChanged( const ViewSharedPtr& rChangedView )
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir             ViewEntryVector::iterator aIter;
139cdf0e10cSrcweir             const ViewEntryVector::iterator aEnd( maViewEntries.end() );
140cdf0e10cSrcweir             if( (aIter=std::find_if( maViewEntries.begin(),
141cdf0e10cSrcweir                                      aEnd,
142cdf0e10cSrcweir                                      boost::bind<bool>(
143cdf0e10cSrcweir                                          std::equal_to< ViewSharedPtr >(),
144cdf0e10cSrcweir                                          boost::bind( &ViewEntry::getView, _1 ),
145cdf0e10cSrcweir                                          boost::cref( rChangedView )))) !=
146cdf0e10cSrcweir                 aEnd )
147cdf0e10cSrcweir             {
148cdf0e10cSrcweir                 // adapt size of given ViewLayer - background layer
149cdf0e10cSrcweir                 // resizes with view.
150cdf0e10cSrcweir                 if( !mbBackgroundLayer )
151cdf0e10cSrcweir                     aIter->mpViewLayer->resize(maBounds);
152cdf0e10cSrcweir             }
153cdf0e10cSrcweir         }
154cdf0e10cSrcweir 
viewsChanged()155cdf0e10cSrcweir         void Layer::viewsChanged()
156cdf0e10cSrcweir         {
157cdf0e10cSrcweir             // adapt size of given ViewLayer - background layer
158cdf0e10cSrcweir             // resizes with view.
159cdf0e10cSrcweir             if( !mbBackgroundLayer )
160cdf0e10cSrcweir             {
161cdf0e10cSrcweir                 std::for_each( maViewEntries.begin(),
162cdf0e10cSrcweir                                maViewEntries.end(),
163cdf0e10cSrcweir                                boost::bind( &ViewLayer::resize,
164cdf0e10cSrcweir                                             boost::bind( &ViewEntry::getViewLayer,
165cdf0e10cSrcweir                                                          _1 ),
166cdf0e10cSrcweir                                             boost::cref(maBounds)));
167cdf0e10cSrcweir             }
168cdf0e10cSrcweir         }
169cdf0e10cSrcweir 
setShapeViews(ShapeSharedPtr const & rShape) const170cdf0e10cSrcweir         void Layer::setShapeViews( ShapeSharedPtr const& rShape ) const
171cdf0e10cSrcweir         {
172cdf0e10cSrcweir             rShape->clearAllViewLayers();
173cdf0e10cSrcweir 
174cdf0e10cSrcweir             std::for_each( maViewEntries.begin(),
175cdf0e10cSrcweir                            maViewEntries.end(),
176cdf0e10cSrcweir                            boost::bind(&Shape::addViewLayer,
177cdf0e10cSrcweir                                        boost::cref(rShape),
178cdf0e10cSrcweir                                        boost::bind(&ViewEntry::getViewLayer,
179cdf0e10cSrcweir                                                    _1),
180cdf0e10cSrcweir                                        false ));
181cdf0e10cSrcweir         }
182cdf0e10cSrcweir 
setPriority(const::basegfx::B1DRange & rPrioRange)183cdf0e10cSrcweir         void Layer::setPriority( const ::basegfx::B1DRange& rPrioRange )
184cdf0e10cSrcweir         {
185cdf0e10cSrcweir             if( !mbBackgroundLayer )
186cdf0e10cSrcweir             {
187cdf0e10cSrcweir                 std::for_each( maViewEntries.begin(),
188cdf0e10cSrcweir                                maViewEntries.end(),
189cdf0e10cSrcweir                                boost::bind( &ViewLayer::setPriority,
190cdf0e10cSrcweir                                             boost::bind( &ViewEntry::getViewLayer,
191cdf0e10cSrcweir                                                          _1 ),
192cdf0e10cSrcweir                                             boost::cref(rPrioRange)));
193cdf0e10cSrcweir             }
194cdf0e10cSrcweir         }
195cdf0e10cSrcweir 
addUpdateRange(::basegfx::B2DRange const & rUpdateRange)196cdf0e10cSrcweir         void Layer::addUpdateRange( ::basegfx::B2DRange const& rUpdateRange )
197cdf0e10cSrcweir         {
198cdf0e10cSrcweir             // TODO(Q1): move this to B2DMultiRange
199cdf0e10cSrcweir             if( !rUpdateRange.isEmpty() )
200cdf0e10cSrcweir                 maUpdateAreas.appendElement( rUpdateRange,
201cdf0e10cSrcweir                                              basegfx::ORIENTATION_POSITIVE );
202cdf0e10cSrcweir         }
203cdf0e10cSrcweir 
updateBounds(ShapeSharedPtr const & rShape)204cdf0e10cSrcweir         void Layer::updateBounds( ShapeSharedPtr const& rShape )
205cdf0e10cSrcweir         {
206cdf0e10cSrcweir             if( !mbBackgroundLayer )
207cdf0e10cSrcweir             {
208cdf0e10cSrcweir                 if( !mbBoundsDirty )
209cdf0e10cSrcweir                     maNewBounds.reset();
210cdf0e10cSrcweir 
211cdf0e10cSrcweir                 maNewBounds.expand( rShape->getUpdateArea() );
212cdf0e10cSrcweir             }
213cdf0e10cSrcweir 
214cdf0e10cSrcweir             mbBoundsDirty = true;
215cdf0e10cSrcweir         }
216cdf0e10cSrcweir 
commitBounds()217cdf0e10cSrcweir         bool Layer::commitBounds()
218cdf0e10cSrcweir         {
219cdf0e10cSrcweir             mbBoundsDirty = false;
220cdf0e10cSrcweir 
221cdf0e10cSrcweir             if( mbBackgroundLayer )
222cdf0e10cSrcweir                 return false;
223cdf0e10cSrcweir 
224cdf0e10cSrcweir             if( maNewBounds == maBounds )
225cdf0e10cSrcweir                 return false;
226cdf0e10cSrcweir 
227cdf0e10cSrcweir             maBounds = maNewBounds;
228cdf0e10cSrcweir             if( std::count_if( maViewEntries.begin(),
229cdf0e10cSrcweir                                maViewEntries.end(),
230cdf0e10cSrcweir                                boost::bind( &ViewLayer::resize,
231cdf0e10cSrcweir                                             boost::bind( &ViewEntry::getViewLayer,
232cdf0e10cSrcweir                                                          _1 ),
233cdf0e10cSrcweir                                             boost::cref(maBounds)) ) == 0 )
234cdf0e10cSrcweir             {
235cdf0e10cSrcweir                 return false;
236cdf0e10cSrcweir             }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir             // layer content invalid, update areas have wrong
239cdf0e10cSrcweir             // coordinates/not sensible anymore.
240cdf0e10cSrcweir             clearUpdateRanges();
241cdf0e10cSrcweir 
242cdf0e10cSrcweir             return true;
243cdf0e10cSrcweir         }
244cdf0e10cSrcweir 
clearUpdateRanges()245cdf0e10cSrcweir         void Layer::clearUpdateRanges()
246cdf0e10cSrcweir         {
247cdf0e10cSrcweir             maUpdateAreas.clear();
248cdf0e10cSrcweir         }
249cdf0e10cSrcweir 
clearContent()250cdf0e10cSrcweir         void Layer::clearContent()
251cdf0e10cSrcweir         {
252cdf0e10cSrcweir             // clear content on all view layers
253cdf0e10cSrcweir             std::for_each( maViewEntries.begin(),
254cdf0e10cSrcweir                            maViewEntries.end(),
255cdf0e10cSrcweir                            boost::bind(
256cdf0e10cSrcweir                                &ViewLayer::clear,
257cdf0e10cSrcweir                                boost::bind(
258cdf0e10cSrcweir                                    &ViewEntry::getViewLayer,
259cdf0e10cSrcweir                                    _1)));
260cdf0e10cSrcweir 
261cdf0e10cSrcweir             // layer content cleared, update areas are not sensible
262cdf0e10cSrcweir             // anymore.
263cdf0e10cSrcweir             clearUpdateRanges();
264cdf0e10cSrcweir         }
265cdf0e10cSrcweir 
266cdf0e10cSrcweir         class LayerEndUpdate : private boost::noncopyable
267cdf0e10cSrcweir         {
268cdf0e10cSrcweir         public:
LayerEndUpdate(LayerSharedPtr const & rLayer)269cdf0e10cSrcweir             LayerEndUpdate( LayerSharedPtr const& rLayer ) :
270cdf0e10cSrcweir                 mpLayer( rLayer )
271cdf0e10cSrcweir             {}
272cdf0e10cSrcweir 
~LayerEndUpdate()273cdf0e10cSrcweir             ~LayerEndUpdate() { if(mpLayer) mpLayer->endUpdate(); }
274cdf0e10cSrcweir 
dismiss()275cdf0e10cSrcweir             void dismiss() { mpLayer.reset(); }
276cdf0e10cSrcweir 
277cdf0e10cSrcweir         private:
278cdf0e10cSrcweir             LayerSharedPtr mpLayer;
279cdf0e10cSrcweir         };
280cdf0e10cSrcweir 
beginUpdate()281cdf0e10cSrcweir         Layer::EndUpdater Layer::beginUpdate()
282cdf0e10cSrcweir         {
283cdf0e10cSrcweir             if( maUpdateAreas.count() )
284cdf0e10cSrcweir             {
285cdf0e10cSrcweir                 // perform proper layer update. That means, setup proper
286cdf0e10cSrcweir                 // clipping, and render each shape that intersects with
287cdf0e10cSrcweir                 // the calculated update area
288cdf0e10cSrcweir                 ::basegfx::B2DPolyPolygon aClip( maUpdateAreas.solveCrossovers() );
289cdf0e10cSrcweir                 aClip = ::basegfx::tools::stripNeutralPolygons(aClip);
290cdf0e10cSrcweir                 aClip = ::basegfx::tools::stripDispensablePolygons(aClip, false);
291cdf0e10cSrcweir 
292cdf0e10cSrcweir                 // actually, if there happen to be shapes with zero
293cdf0e10cSrcweir                 // update area in the maUpdateAreas vector, the
294cdf0e10cSrcweir                 // resulting clip polygon will be empty.
295cdf0e10cSrcweir                 if( aClip.count() )
296cdf0e10cSrcweir                 {
297cdf0e10cSrcweir                     // set clip to all view layers
298cdf0e10cSrcweir                     std::for_each( maViewEntries.begin(),
299cdf0e10cSrcweir                                    maViewEntries.end(),
300cdf0e10cSrcweir                                    boost::bind(
301cdf0e10cSrcweir                                        &ViewLayer::setClip,
302cdf0e10cSrcweir                                        boost::bind(
303cdf0e10cSrcweir                                            &ViewEntry::getViewLayer,
304cdf0e10cSrcweir                                            _1),
305cdf0e10cSrcweir                                        boost::cref(aClip)));
306cdf0e10cSrcweir 
307cdf0e10cSrcweir                     // clear update area on all view layers
308cdf0e10cSrcweir                     std::for_each( maViewEntries.begin(),
309cdf0e10cSrcweir                                    maViewEntries.end(),
310cdf0e10cSrcweir                                    boost::bind(
311cdf0e10cSrcweir                                        &ViewLayer::clear,
312cdf0e10cSrcweir                                        boost::bind(
313cdf0e10cSrcweir                                            &ViewEntry::getViewLayer,
314cdf0e10cSrcweir                                            _1)));
315cdf0e10cSrcweir 
316cdf0e10cSrcweir                     mbClipSet = true;
317cdf0e10cSrcweir                 }
318cdf0e10cSrcweir             }
319cdf0e10cSrcweir 
320cdf0e10cSrcweir             return EndUpdater(new LayerEndUpdate(shared_from_this()));
321cdf0e10cSrcweir         }
322cdf0e10cSrcweir 
endUpdate()323cdf0e10cSrcweir         void Layer::endUpdate()
324cdf0e10cSrcweir         {
325cdf0e10cSrcweir             if( mbClipSet )
326cdf0e10cSrcweir             {
327cdf0e10cSrcweir                 mbClipSet = false;
328cdf0e10cSrcweir 
329cdf0e10cSrcweir                 basegfx::B2DPolyPolygon aEmptyClip;
330cdf0e10cSrcweir                 std::for_each( maViewEntries.begin(),
331cdf0e10cSrcweir                                maViewEntries.end(),
332cdf0e10cSrcweir                                boost::bind(
333cdf0e10cSrcweir                                    &ViewLayer::setClip,
334cdf0e10cSrcweir                                    boost::bind(
335cdf0e10cSrcweir                                        &ViewEntry::getViewLayer,
336cdf0e10cSrcweir                                        _1),
337cdf0e10cSrcweir                                    boost::cref(aEmptyClip)));
338cdf0e10cSrcweir             }
339cdf0e10cSrcweir 
340cdf0e10cSrcweir             clearUpdateRanges();
341cdf0e10cSrcweir         }
342cdf0e10cSrcweir 
isInsideUpdateArea(ShapeSharedPtr const & rShape) const343cdf0e10cSrcweir         bool Layer::isInsideUpdateArea( ShapeSharedPtr const& rShape ) const
344cdf0e10cSrcweir         {
345cdf0e10cSrcweir             return maUpdateAreas.overlaps( rShape->getUpdateArea() );
346cdf0e10cSrcweir         }
347cdf0e10cSrcweir 
createBackgroundLayer(const basegfx::B2DRange & rMaxLayerBounds)348cdf0e10cSrcweir         LayerSharedPtr Layer::createBackgroundLayer( const basegfx::B2DRange& rMaxLayerBounds )
349cdf0e10cSrcweir         {
350cdf0e10cSrcweir             return LayerSharedPtr(new Layer( rMaxLayerBounds,
351cdf0e10cSrcweir                                              BackgroundLayer ));
352cdf0e10cSrcweir         }
353cdf0e10cSrcweir 
createLayer(const basegfx::B2DRange & rMaxLayerBounds)354cdf0e10cSrcweir         LayerSharedPtr Layer::createLayer( const basegfx::B2DRange& rMaxLayerBounds )
355cdf0e10cSrcweir         {
356cdf0e10cSrcweir             return LayerSharedPtr( new Layer( rMaxLayerBounds ) );
357cdf0e10cSrcweir         }
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     }
360cdf0e10cSrcweir }
361