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