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