1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <com/sun/star/beans/XPropertySet.hpp>
22 
23 #include <sal/log.hxx>
24 #include <osl/diagnose.h>
25 
26 #include <algorithm>
27 
28 #include "backgroundshape.hxx"
29 #include <slideshowexceptions.hxx>
30 #include <slideshowcontext.hxx>
31 #include "gdimtftools.hxx"
32 #include <shape.hxx>
33 #include "viewbackgroundshape.hxx"
34 
35 
36 using namespace ::com::sun::star;
37 
38 
39 namespace slideshow::internal
40 {
41         namespace {
42 
43         /** Representation of a draw document's background shape.
44 
45             This class implements the Shape interface for the
46             background shape. Since the background shape is neither
47             animatable nor attributable, those more specialized
48             derivations of the Shape interface are not implemented
49             here.
50 
51             @attention this class is to be treated 'final', i.e. one
52             should not derive from it.
53          */
54         class BackgroundShape : public Shape
55         {
56         public:
57             /** Create the background shape.
58 
59                 This method creates a shape that handles the
60                 peculiarities of the draw API regarding background
61                 content.
62              */
63             BackgroundShape( const css::uno::Reference< css::drawing::XDrawPage >& xDrawPage,
64                              const css::uno::Reference< css::drawing::XDrawPage >& xMasterPage,
65                              const SlideShowContext&                    rContext ); // throw ShapeLoadFailedException;
66 
67             virtual css::uno::Reference<
68                 css::drawing::XShape > getXShape() const override;
69 
70             // View layer methods
71 
72 
73             virtual void addViewLayer( const ViewLayerSharedPtr&    rNewLayer,
74                                        bool                         bRedrawLayer ) override;
75             virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer ) override;
76             virtual void clearAllViewLayers() override;
77 
78 
79             // attribute methods
80 
81 
82             virtual ::basegfx::B2DRectangle getBounds() const override;
83             virtual ::basegfx::B2DRectangle getDomBounds() const override;
84             virtual ::basegfx::B2DRectangle getUpdateArea() const override;
85             virtual bool isVisible() const override;
86             virtual double getPriority() const override;
isForeground() const87             virtual bool isForeground() const override { return false; }
88             virtual bool isBackgroundDetached() const override;
89 
90 
91             // render methods
92 
93 
94             virtual bool update() const override;
95             virtual bool render() const override;
96             virtual bool isContentChanged() const override;
97 
98         private:
99             /// The metafile actually representing the Shape
100             GDIMetaFileSharedPtr        mpMtf;
101 
102             // The attributes of this Shape
103             ::basegfx::B2DRectangle     maBounds; // always needed for rendering
104 
105             /// the list of active view shapes (one for each registered view layer)
106             typedef ::std::vector< ViewBackgroundShapeSharedPtr > ViewBackgroundShapeVector;
107             ViewBackgroundShapeVector   maViewShapes;
108         };
109 
110         }
111 
BackgroundShape(const uno::Reference<drawing::XDrawPage> & xDrawPage,const uno::Reference<drawing::XDrawPage> & xMasterPage,const SlideShowContext & rContext)112         BackgroundShape::BackgroundShape( const uno::Reference< drawing::XDrawPage >& xDrawPage,
113                                           const uno::Reference< drawing::XDrawPage >& xMasterPage,
114                                           const SlideShowContext&                     rContext ) :
115             mpMtf(),
116             maBounds(),
117             maViewShapes()
118         {
119             uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
120                                                             uno::UNO_QUERY_THROW );
121             // first try the page background (overrides
122             // masterpage background), then try masterpage
123             GDIMetaFileSharedPtr xMtf = getMetaFile(uno::Reference<lang::XComponent>(xDrawPage, uno::UNO_QUERY),
124                                                     xDrawPage, MTF_LOAD_BACKGROUND_ONLY,
125                                                     rContext.mxComponentContext);
126 
127             if (!xMtf)
128             {
129                 xMtf = getMetaFile( uno::Reference<lang::XComponent>(xMasterPage, uno::UNO_QUERY),
130                                     xDrawPage, MTF_LOAD_BACKGROUND_ONLY,
131                                     rContext.mxComponentContext );
132             }
133 
134             if (!xMtf)
135             {
136                 throw ShapeLoadFailedException();
137             }
138 
139             // there is a special background shape, add it
140             // as the first one
141 
142             sal_Int32 nDocWidth=0;
143             sal_Int32 nDocHeight=0;
144             xPropSet->getPropertyValue("Width") >>= nDocWidth;
145             xPropSet->getPropertyValue("Height") >>= nDocHeight;
146 
147             mpMtf = xMtf;
148             maBounds = ::basegfx::B2DRectangle( 0,0,nDocWidth, nDocHeight );
149         }
150 
getXShape() const151         uno::Reference< drawing::XShape > BackgroundShape::getXShape() const
152         {
153             // no real XShape representative
154             return uno::Reference< drawing::XShape >();
155         }
156 
addViewLayer(const ViewLayerSharedPtr & rNewLayer,bool bRedrawLayer)157         void BackgroundShape::addViewLayer( const ViewLayerSharedPtr&   rNewLayer,
158                                             bool                        bRedrawLayer )
159         {
160             // already added?
161             if( ::std::any_of( maViewShapes.begin(),
162                                maViewShapes.end(),
163                                [&rNewLayer]( const ViewBackgroundShapeSharedPtr& pBgShape )
164                                { return pBgShape->getViewLayer() == rNewLayer; } ) )
165             {
166                 // yes, nothing to do
167                 return;
168             }
169 
170             maViewShapes.push_back(
171                 std::make_shared<ViewBackgroundShape>(
172                     rNewLayer, maBounds ) );
173 
174             // render the Shape on the newly added ViewLayer
175             if( bRedrawLayer )
176                 maViewShapes.back()->render( mpMtf );
177         }
178 
removeViewLayer(const ViewLayerSharedPtr & rLayer)179         bool BackgroundShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
180         {
181             const ViewBackgroundShapeVector::iterator aEnd( maViewShapes.end() );
182 
183             OSL_ENSURE( ::std::count_if(maViewShapes.begin(),
184                                         aEnd,
185                                         [&rLayer]( const ViewBackgroundShapeSharedPtr& pBgShape )
186                                         { return pBgShape->getViewLayer() == rLayer; } ) < 2,
187                         "BackgroundShape::removeViewLayer(): Duplicate ViewLayer entries!" );
188 
189             ViewBackgroundShapeVector::iterator aIter;
190 
191             if( (aIter=::std::remove_if( maViewShapes.begin(),
192                                          aEnd,
193                                          [&rLayer]( const ViewBackgroundShapeSharedPtr& pBgShape )
194                                          { return pBgShape->getViewLayer() == rLayer; } )) == aEnd )
195             {
196                 // view layer seemingly was not added, failed
197                 return false;
198             }
199 
200             // actually erase from container
201             maViewShapes.erase( aIter, aEnd );
202 
203             return true;
204         }
205 
clearAllViewLayers()206         void BackgroundShape::clearAllViewLayers()
207         {
208             maViewShapes.clear();
209         }
210 
getBounds() const211         ::basegfx::B2DRectangle BackgroundShape::getBounds() const
212         {
213             return maBounds;
214         }
215 
getDomBounds() const216         ::basegfx::B2DRectangle BackgroundShape::getDomBounds() const
217         {
218             return maBounds;
219         }
220 
getUpdateArea() const221         ::basegfx::B2DRectangle BackgroundShape::getUpdateArea() const
222         {
223             // TODO(F1): Need to expand background, too, when
224             // antialiasing?
225 
226             // no transformation etc. possible for background shape
227             return maBounds;
228         }
229 
isVisible() const230         bool BackgroundShape::isVisible() const
231         {
232             return true;
233         }
234 
getPriority() const235         double BackgroundShape::getPriority() const
236         {
237             return 0.0; // lowest prio, we're the background
238         }
239 
update() const240         bool BackgroundShape::update() const
241         {
242             return render();
243         }
244 
render() const245         bool BackgroundShape::render() const
246         {
247             SAL_INFO( "slideshow", "::presentation::internal::BackgroundShape::render()" );
248             SAL_INFO( "slideshow", "::presentation::internal::BackgroundShape: 0x" << std::hex << this );
249 
250             // gcc again...
251             const ::basegfx::B2DRectangle& rCurrBounds( BackgroundShape::getBounds() );
252 
253             if( rCurrBounds.getRange().equalZero() )
254             {
255                 // zero-sized shapes are effectively invisible,
256                 // thus, we save us the rendering...
257                 return true;
258             }
259 
260             // redraw all view shapes, by calling their render() method
261             if( ::std::count_if( maViewShapes.begin(),
262                                  maViewShapes.end(),
263                                  [this]( const ViewBackgroundShapeSharedPtr& pBgShape )
264                                  { return pBgShape->render( this->mpMtf ); } )
265                 != static_cast<ViewBackgroundShapeVector::difference_type>(maViewShapes.size()) )
266             {
267                 // at least one of the ViewBackgroundShape::render() calls did return
268                 // false - update failed on at least one ViewLayer
269                 return false;
270             }
271 
272             return true;
273         }
274 
isContentChanged() const275         bool BackgroundShape::isContentChanged() const
276         {
277             return false;
278         }
279 
isBackgroundDetached() const280         bool BackgroundShape::isBackgroundDetached() const
281         {
282             return false; // we're not animatable
283         }
284 
285 
createBackgroundShape(const uno::Reference<drawing::XDrawPage> & xDrawPage,const uno::Reference<drawing::XDrawPage> & xMasterPage,const SlideShowContext & rContext)286        ShapeSharedPtr createBackgroundShape(
287             const uno::Reference< drawing::XDrawPage >& xDrawPage,
288             const uno::Reference< drawing::XDrawPage >& xMasterPage,
289             const SlideShowContext&                     rContext )
290         {
291             return std::make_shared<BackgroundShape>(
292                     xDrawPage,
293                     xMasterPage,
294                     rContext );
295         }
296 }
297 
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
299