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_slideshow.hxx"
26 
27 // must be first
28 #include <canvas/debug.hxx>
29 
30 #include <com/sun/star/awt/Rectangle.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/awt/FontWeight.hpp>
33 #include <rtl/logfile.hxx>
34 
35 #include <vcl/metaact.hxx>
36 #include <vcl/gdimtf.hxx>
37 
38 #include <basegfx/numeric/ftools.hxx>
39 
40 #include <boost/bind.hpp>
41 
42 #include <cmath> // for trigonometry and fabs
43 #include <algorithm>
44 #include <functional>
45 #include <limits>
46 
47 #include "backgroundshape.hxx"
48 #include "slideshowexceptions.hxx"
49 #include "slideshowcontext.hxx"
50 #include "gdimtftools.hxx"
51 #include "shape.hxx"
52 #include "viewbackgroundshape.hxx"
53 
54 
55 using namespace ::com::sun::star;
56 
57 
58 namespace slideshow
59 {
60     namespace internal
61     {
62         /** Representation of a draw document's background shape.
63 
64             This class implements the Shape interface for the
65             background shape. Since the background shape is neither
66             animatable nor attributable, those more specialized
67             derivations of the Shape interface are not implemented
68             here.
69 
70             @attention this class is to be treated 'final', i.e. one
71             should not derive from it.
72          */
73         class BackgroundShape : public Shape
74         {
75         public:
76             /** Create the background shape.
77 
78             	This method creates a shape that handles the
79             	peculiarities of the draw API regarding background
80             	content.
81              */
82             BackgroundShape( const ::com::sun::star::uno::Reference<
83                              	::com::sun::star::drawing::XDrawPage >& xDrawPage,
84                              const ::com::sun::star::uno::Reference<
85                              	::com::sun::star::drawing::XDrawPage >& xMasterPage,
86                              const SlideShowContext&                    rContext ); // throw ShapeLoadFailedException;
87 
88             virtual ::com::sun::star::uno::Reference<
89                 ::com::sun::star::drawing::XShape > getXShape() const;
90 
91             // View layer methods
92             //------------------------------------------------------------------
93 
94             virtual void addViewLayer( const ViewLayerSharedPtr& 	rNewLayer,
95                                        bool							bRedrawLayer );
96             virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer );
97             virtual bool clearAllViewLayers();
98 
99 
100             // attribute methods
101             //------------------------------------------------------------------
102 
103             virtual ::basegfx::B2DRectangle getBounds() const;
104             virtual ::basegfx::B2DRectangle getDomBounds() const;
105             virtual ::basegfx::B2DRectangle getUpdateArea() const;
106             virtual bool isVisible() const;
107             virtual double getPriority() const;
108             virtual bool isBackgroundDetached() const;
109 
110 
111             // render methods
112             //------------------------------------------------------------------
113 
114             virtual bool update() const;
115             virtual bool render() const;
116             virtual bool isContentChanged() const;
117 
118         private:
119             /// The metafile actually representing the Shape
120             GDIMetaFileSharedPtr		mpMtf;
121 
122             // The attributes of this Shape
123             ::basegfx::B2DRectangle		maBounds; // always needed for rendering
124 
125             /// the list of active view shapes (one for each registered view layer)
126             typedef ::std::vector< ViewBackgroundShapeSharedPtr > ViewBackgroundShapeVector;
127             ViewBackgroundShapeVector	maViewShapes;
128         };
129 
130 
131         ////////////////////////////////////////////////////////////////////////////////
132 
133 
BackgroundShape(const uno::Reference<drawing::XDrawPage> & xDrawPage,const uno::Reference<drawing::XDrawPage> & xMasterPage,const SlideShowContext & rContext)134         BackgroundShape::BackgroundShape( const uno::Reference< drawing::XDrawPage >& xDrawPage,
135                                           const uno::Reference< drawing::XDrawPage >& xMasterPage,
136                                           const SlideShowContext&                     rContext ) :
137             mpMtf(),
138             maBounds(),
139             maViewShapes()
140         {
141             uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
142                                                             uno::UNO_QUERY_THROW );
143             GDIMetaFileSharedPtr pMtf( new GDIMetaFile() );
144 
145             // first try the page background (overrides
146             // masterpage background), then try masterpage
147             if( !getMetaFile( uno::Reference<lang::XComponent>(xDrawPage, uno::UNO_QUERY),
148                               xDrawPage, *pMtf, MTF_LOAD_BACKGROUND_ONLY,
149                               rContext.mxComponentContext ) &&
150                 !getMetaFile( uno::Reference<lang::XComponent>(xMasterPage, uno::UNO_QUERY),
151                               xDrawPage, *pMtf, MTF_LOAD_BACKGROUND_ONLY,
152                               rContext.mxComponentContext ))
153             {
154                 throw ShapeLoadFailedException();
155             }
156 
157             // there is a special background shape, add it
158             // as the first one
159             // ---------------------------------------------------
160 
161             sal_Int32 nDocWidth=0;
162             sal_Int32 nDocHeight=0;
163             xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= nDocWidth;
164             xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= nDocHeight;
165 
166             mpMtf = pMtf;
167             maBounds = ::basegfx::B2DRectangle( 0,0,nDocWidth, nDocHeight );
168         }
169 
getXShape() const170         uno::Reference< drawing::XShape > BackgroundShape::getXShape() const
171         {
172             // no real XShape representative
173             return uno::Reference< drawing::XShape >();
174         }
175 
addViewLayer(const ViewLayerSharedPtr & rNewLayer,bool bRedrawLayer)176         void BackgroundShape::addViewLayer( const ViewLayerSharedPtr&	rNewLayer,
177                                             bool						bRedrawLayer )
178         {
179             ViewBackgroundShapeVector::iterator aEnd( maViewShapes.end() );
180 
181             // already added?
182             if( ::std::find_if( maViewShapes.begin(),
183                                 aEnd,
184                                 ::boost::bind<bool>(
185                                     ::std::equal_to< ViewLayerSharedPtr >(),
186                                     ::boost::bind( &ViewBackgroundShape::getViewLayer,
187                                                    _1 ),
188                                     ::boost::cref( rNewLayer ) ) ) != aEnd )
189             {
190                 // yes, nothing to do
191                 return;
192             }
193 
194             maViewShapes.push_back(
195                 ViewBackgroundShapeSharedPtr(
196                     new ViewBackgroundShape( rNewLayer,
197                                              maBounds ) ) );
198 
199             // render the Shape on the newly added ViewLayer
200             if( bRedrawLayer )
201                 maViewShapes.back()->render( mpMtf );
202         }
203 
removeViewLayer(const ViewLayerSharedPtr & rLayer)204         bool BackgroundShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
205         {
206             const ViewBackgroundShapeVector::iterator aEnd( maViewShapes.end() );
207 
208             OSL_ENSURE( ::std::count_if(maViewShapes.begin(),
209                                         aEnd,
210                                         ::boost::bind<bool>(
211                                             ::std::equal_to< ViewLayerSharedPtr >(),
212                                             ::boost::bind( &ViewBackgroundShape::getViewLayer,
213                                                            _1 ),
214                                             ::boost::cref( rLayer ) ) ) < 2,
215                         "BackgroundShape::removeViewLayer(): Duplicate ViewLayer entries!" );
216 
217             ViewBackgroundShapeVector::iterator aIter;
218 
219             if( (aIter=::std::remove_if( maViewShapes.begin(),
220                                          aEnd,
221                                          ::boost::bind<bool>(
222                                              ::std::equal_to< ViewLayerSharedPtr >(),
223                                              ::boost::bind( &ViewBackgroundShape::getViewLayer,
224                                                             _1 ),
225                                              ::boost::cref( rLayer ) ) )) == aEnd )
226             {
227                 // view layer seemingly was not added, failed
228                 return false;
229             }
230 
231             // actually erase from container
232             maViewShapes.erase( aIter, aEnd );
233 
234             return true;
235         }
236 
clearAllViewLayers()237         bool BackgroundShape::clearAllViewLayers()
238         {
239             maViewShapes.clear();
240             return true;
241         }
242 
getBounds() const243         ::basegfx::B2DRectangle BackgroundShape::getBounds() const
244         {
245             return maBounds;
246         }
247 
getDomBounds() const248         ::basegfx::B2DRectangle BackgroundShape::getDomBounds() const
249         {
250             return maBounds;
251         }
252 
getUpdateArea() const253         ::basegfx::B2DRectangle BackgroundShape::getUpdateArea() const
254         {
255             // TODO(F1): Need to expand background, too, when
256             // antialiasing?
257 
258             // no transformation etc. possible for background shape
259             return maBounds;
260         }
261 
isVisible() const262         bool BackgroundShape::isVisible() const
263         {
264             return true;
265         }
266 
getPriority() const267         double BackgroundShape::getPriority() const
268         {
269         	return 0.0; // lowest prio, we're the background
270         }
271 
update() const272         bool BackgroundShape::update() const
273         {
274             return render();
275         }
276 
render() const277         bool BackgroundShape::render() const
278         {
279             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::BackgroundShape::render()" );
280             RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::presentation::internal::BackgroundShape: 0x%X", this );
281 
282             // gcc again...
283             const ::basegfx::B2DRectangle& rCurrBounds( BackgroundShape::getBounds() );
284 
285             if( rCurrBounds.getRange().equalZero() )
286             {
287                 // zero-sized shapes are effectively invisible,
288                 // thus, we save us the rendering...
289                 return true;
290             }
291 
292             // redraw all view shapes, by calling their render() method
293             if( ::std::count_if( maViewShapes.begin(),
294                                  maViewShapes.end(),
295                                  ::boost::bind( &ViewBackgroundShape::render,
296                                                 _1,
297                                                 ::boost::cref( mpMtf ) ) )
298                 != static_cast<ViewBackgroundShapeVector::difference_type>(maViewShapes.size()) )
299             {
300                 // at least one of the ViewBackgroundShape::render() calls did return
301                 // false - update failed on at least one ViewLayer
302                 return false;
303             }
304 
305             return true;
306         }
307 
isContentChanged() const308         bool BackgroundShape::isContentChanged() const
309         {
310             return false;
311         }
312 
isBackgroundDetached() const313         bool BackgroundShape::isBackgroundDetached() const
314         {
315             return false; // we're not animatable
316         }
317 
318         //////////////////////////////////////////////////////////
319 
createBackgroundShape(const uno::Reference<drawing::XDrawPage> & xDrawPage,const uno::Reference<drawing::XDrawPage> & xMasterPage,const SlideShowContext & rContext)320         ShapeSharedPtr createBackgroundShape(
321             const uno::Reference< drawing::XDrawPage >& xDrawPage,
322             const uno::Reference< drawing::XDrawPage >& xMasterPage,
323             const SlideShowContext&                     rContext )
324         {
325             return ShapeSharedPtr(
326                 new BackgroundShape(
327                     xDrawPage,
328                     xMasterPage,
329                     rContext ));
330         }
331     }
332 }
333