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 #include <tools/diagnose_ex.h> 34 35 #include <animatedsprite.hxx> 36 37 #include <cppcanvas/canvas.hxx> 38 #include <canvas/canvastools.hxx> 39 40 #include <basegfx/vector/b2dvector.hxx> 41 #include <basegfx/point/b2dpoint.hxx> 42 #include <basegfx/matrix/b2dhommatrix.hxx> 43 #include <basegfx/numeric/ftools.hxx> 44 45 46 using namespace ::com::sun::star; 47 48 namespace slideshow 49 { 50 namespace internal 51 { 52 AnimatedSprite::AnimatedSprite( const ViewLayerSharedPtr& rViewLayer, 53 const ::basegfx::B2DSize& rSpriteSizePixel, 54 double nSpritePrio ) : 55 mpViewLayer( rViewLayer ), 56 mpSprite(), 57 maEffectiveSpriteSizePixel( rSpriteSizePixel ), 58 maContentPixelOffset(), 59 mnSpritePrio(nSpritePrio), 60 mnAlpha(0.0), 61 maPosPixel(), 62 maClip(), 63 maTransform(), 64 mbSpriteVisible( false ) 65 { 66 ENSURE_OR_THROW( mpViewLayer, "AnimatedSprite::AnimatedSprite(): Invalid view layer" ); 67 68 // Add half a pixel tolerance to sprite size, since we later on compare 69 // against it in resize(). And view transformations will almost never yield 70 // the same data bits when transforming to device coordinates 71 maEffectiveSpriteSizePixel += ::basegfx::B2DSize(0.5, 0.5); 72 73 mpSprite = mpViewLayer->createSprite( maEffectiveSpriteSizePixel, 74 mnSpritePrio ); 75 76 ENSURE_OR_THROW( mpSprite, "AnimatedSprite::AnimatedSprite(): Could not create sprite" ); 77 } 78 79 ::cppcanvas::CanvasSharedPtr AnimatedSprite::getContentCanvas() const 80 { 81 ENSURE_OR_THROW( mpViewLayer->getCanvas(), "AnimatedSprite::getContentCanvas(): No view layer canvas" ); 82 83 const ::cppcanvas::CanvasSharedPtr pContentCanvas( mpSprite->getContentCanvas() ); 84 pContentCanvas->clear(); 85 86 // extract linear part of canvas view transformation 87 // (linear means: without translational components). The 88 // only translation that is imposed at the view transform 89 // is the local content pixel offset. 90 // 91 // We can apply that directly here, no need to call 92 // aLinearTransform.translate(), since, as said above, the 93 // last column of aLinearTransform is assumed [0 0 1] 94 ::basegfx::B2DHomMatrix aLinearTransform( mpViewLayer->getTransformation() ); 95 aLinearTransform.set( 0, 2, maContentPixelOffset.getX() ); 96 aLinearTransform.set( 1, 2, maContentPixelOffset.getY() ); 97 98 // apply linear part of canvas view transformation to sprite canvas 99 pContentCanvas->setTransformation( aLinearTransform ); 100 101 return pContentCanvas; 102 } 103 104 bool AnimatedSprite::resize( const ::basegfx::B2DSize& rSpriteSizePixel ) 105 { 106 // Enlarge or reduce the sprite size, if necessary. This 107 // method employs a strategy similar to container, when 108 // allocating memory: size is doubled or halved everytime 109 // the limit is reached. This makes for amortized constant 110 // time in runtime complexity. Note that we take exact 111 // powers of two here, since several HW-accelerated canvas 112 // implementations are limited to such sprite sizes 113 // (otherwise, those implementations would internally 114 // round up, too, wasting precious mem). 115 ::basegfx::B2DSize aNewSize( maEffectiveSpriteSizePixel ); 116 bool bNeedResize( false ); 117 118 if( rSpriteSizePixel.getX() > maEffectiveSpriteSizePixel.getX() || 119 rSpriteSizePixel.getX() < 0.5*maEffectiveSpriteSizePixel.getX() ) 120 { 121 // enlarge or shrink width 122 aNewSize.setX( ::canvas::tools::nextPow2( ::basegfx::fround(rSpriteSizePixel.getX()) ) ); 123 bNeedResize = true; 124 } 125 126 if( rSpriteSizePixel.getY() > maEffectiveSpriteSizePixel.getY() || 127 rSpriteSizePixel.getY() < 0.5*maEffectiveSpriteSizePixel.getY() ) 128 { 129 // enlarge or shrink height, by doubling it 130 aNewSize.setY( ::canvas::tools::nextPow2( ::basegfx::fround(rSpriteSizePixel.getY()) ) ); 131 bNeedResize = true; 132 } 133 134 if( bNeedResize ) 135 { 136 // as the old sprite might have already been altered 137 // (and therefore been placed in the update list of 138 // the spritecanvas for this frame), must hide it 139 // here, to ensure it's not visible on screen any 140 // longer. 141 mpSprite->hide(); 142 143 maEffectiveSpriteSizePixel = aNewSize; 144 mpSprite = mpViewLayer->createSprite( maEffectiveSpriteSizePixel, 145 mnSpritePrio ); 146 147 ENSURE_OR_THROW( mpSprite, 148 "AnimatedSprite::resize(): Could not create new sprite" ); 149 150 // set attributes similar to previous sprite 151 if( mpSprite && mbSpriteVisible ) 152 { 153 mpSprite->show(); 154 mpSprite->setAlpha( mnAlpha ); 155 156 if( maPosPixel ) 157 mpSprite->movePixel( *maPosPixel ); 158 159 if( maClip ) 160 mpSprite->setClip( *maClip ); 161 } 162 } 163 164 return mpSprite; 165 } 166 167 void AnimatedSprite::setPixelOffset( const ::basegfx::B2DSize& rPixelOffset ) 168 { 169 maContentPixelOffset = rPixelOffset; 170 } 171 172 ::basegfx::B2DSize AnimatedSprite::getPixelOffset() const 173 { 174 return maContentPixelOffset; 175 } 176 177 void AnimatedSprite::movePixel( const ::basegfx::B2DPoint& rNewPos ) 178 { 179 maPosPixel.reset( rNewPos ); 180 mpSprite->movePixel( rNewPos ); 181 } 182 183 void AnimatedSprite::setAlpha( double nAlpha ) 184 { 185 mnAlpha = nAlpha; 186 mpSprite->setAlpha( nAlpha ); 187 } 188 189 void AnimatedSprite::clip( const ::basegfx::B2DPolyPolygon& rClip ) 190 { 191 maClip.reset( rClip ); 192 mpSprite->setClipPixel( rClip ); 193 } 194 195 void AnimatedSprite::clip() 196 { 197 maClip.reset(); 198 mpSprite->setClip(); 199 } 200 201 void AnimatedSprite::transform( const ::basegfx::B2DHomMatrix& rTransform ) 202 { 203 maTransform.reset( rTransform ); 204 mpSprite->transform( rTransform ); 205 } 206 207 void AnimatedSprite::setPriority( double nPrio ) 208 { 209 mpSprite->setPriority( nPrio ); 210 } 211 212 void AnimatedSprite::hide() 213 { 214 mpSprite->hide(); 215 mbSpriteVisible = false; 216 } 217 218 void AnimatedSprite::show() 219 { 220 mbSpriteVisible = true; 221 mpSprite->show(); 222 } 223 224 } 225 } 226