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