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_vcl.hxx" 30 31 #include "impanmvw.hxx" 32 #include <vcl/virdev.hxx> 33 #include <vcl/window.hxx> 34 #include <vcl/salbtype.hxx> 35 36 // ---------------- 37 // - ImplAnimView - 38 // ---------------- 39 40 ImplAnimView::ImplAnimView( Animation* pParent, OutputDevice* pOut, 41 const Point& rPt, const Size& rSz, 42 sal_uLong nExtraData, 43 OutputDevice* pFirstFrameOutDev ) : 44 mpParent ( pParent ), 45 mpOut ( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ), 46 mnExtraData ( nExtraData ), 47 maPt ( rPt ), 48 maSz ( rSz ), 49 maSzPix ( mpOut->LogicToPixel( maSz ) ), 50 maClip ( mpOut->GetClipRegion() ), 51 mpBackground ( new VirtualDevice ), 52 mpRestore ( new VirtualDevice ), 53 meLastDisposal ( DISPOSE_BACK ), 54 mbPause ( sal_False ), 55 mbMarked ( sal_False ), 56 mbHMirr ( maSz.Width() < 0L ), 57 mbVMirr ( maSz.Height() < 0L ) 58 { 59 mpParent->ImplIncAnimCount(); 60 61 // mirrored horizontically? 62 if( mbHMirr ) 63 { 64 maDispPt.X() = maPt.X() + maSz.Width() + 1L; 65 maDispSz.Width() = -maSz.Width(); 66 maSzPix.Width() = -maSzPix.Width(); 67 } 68 else 69 { 70 maDispPt.X() = maPt.X(); 71 maDispSz.Width() = maSz.Width(); 72 } 73 74 // mirrored vertically? 75 if( mbVMirr ) 76 { 77 maDispPt.Y() = maPt.Y() + maSz.Height() + 1L; 78 maDispSz.Height() = -maSz.Height(); 79 maSzPix.Height() = -maSzPix.Height(); 80 } 81 else 82 { 83 maDispPt.Y() = maPt.Y(); 84 maDispSz.Height() = maSz.Height(); 85 } 86 87 // save background 88 mpBackground->SetOutputSizePixel( maSzPix ); 89 90 if( mpOut->GetOutDevType() == OUTDEV_WINDOW ) 91 { 92 MapMode aTempMap( mpOut->GetMapMode() ); 93 aTempMap.SetOrigin( Point() ); 94 mpBackground->SetMapMode( aTempMap ); 95 ( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground ); 96 mpBackground->SetMapMode( MapMode() ); 97 } 98 else 99 mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut ); 100 101 // initial drawing to actual position 102 ImplDrawToPos( mpParent->ImplGetCurPos() ); 103 104 // if first frame OutputDevice is set, update variables now for real OutputDevice 105 if( pFirstFrameOutDev ) 106 maClip = ( mpOut = pOut )->GetClipRegion(); 107 } 108 109 // ------------------------------------------------------------------------ 110 111 ImplAnimView::~ImplAnimView() 112 { 113 delete mpBackground; 114 delete mpRestore; 115 116 mpParent->ImplDecAnimCount(); 117 } 118 119 // ------------------------------------------------------------------------ 120 121 sal_Bool ImplAnimView::ImplMatches( OutputDevice* pOut, long nExtraData ) const 122 { 123 sal_Bool bRet = sal_False; 124 125 if( nExtraData ) 126 { 127 if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) ) 128 bRet = sal_True; 129 } 130 else if( !pOut || ( pOut == mpOut ) ) 131 bRet = sal_True; 132 133 return bRet; 134 } 135 136 // ------------------------------------------------------------------------ 137 138 void ImplAnimView::ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix ) 139 { 140 const Size& rAnmSize = mpParent->GetDisplaySizePixel(); 141 Point aPt2( rAnm.aPosPix.X() + rAnm.aSizePix.Width() - 1L, 142 rAnm.aPosPix.Y() + rAnm.aSizePix.Height() - 1L ); 143 double fFactX, fFactY; 144 145 // calculate x scaling 146 if( rAnmSize.Width() > 1L ) 147 fFactX = (double) ( maSzPix.Width() - 1L ) / ( rAnmSize.Width() - 1L ); 148 else 149 fFactX = 1.0; 150 151 // calculate y scaling 152 if( rAnmSize.Height() > 1L ) 153 fFactY = (double) ( maSzPix.Height() - 1L ) / ( rAnmSize.Height() - 1L ); 154 else 155 fFactY = 1.0; 156 157 rPosPix.X() = FRound( rAnm.aPosPix.X() * fFactX ); 158 rPosPix.Y() = FRound( rAnm.aPosPix.Y() * fFactY ); 159 160 aPt2.X() = FRound( aPt2.X() * fFactX ); 161 aPt2.Y() = FRound( aPt2.Y() * fFactY ); 162 163 rSizePix.Width() = aPt2.X() - rPosPix.X() + 1L; 164 rSizePix.Height() = aPt2.Y() - rPosPix.Y() + 1L; 165 166 // mirrored horizontically? 167 if( mbHMirr ) 168 rPosPix.X() = maSzPix.Width() - 1L - aPt2.X(); 169 170 // mirrored vertically? 171 if( mbVMirr ) 172 rPosPix.Y() = maSzPix.Height() - 1L - aPt2.Y(); 173 } 174 175 // ------------------------------------------------------------------------ 176 177 void ImplAnimView::ImplDrawToPos( sal_uLong nPos ) 178 { 179 VirtualDevice aVDev; 180 Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL; 181 182 aVDev.SetOutputSizePixel( maSzPix, sal_False ); 183 nPos = Min( nPos, (sal_uLong) mpParent->Count() - 1UL ); 184 185 for( sal_uLong i = 0UL; i <= nPos; i++ ) 186 ImplDraw( i, &aVDev ); 187 188 if( pOldClip ) 189 mpOut->SetClipRegion( maClip ); 190 191 mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, aVDev ); 192 193 if( pOldClip ) 194 { 195 mpOut->SetClipRegion( *pOldClip ); 196 delete pOldClip; 197 } 198 } 199 200 // ------------------------------------------------------------------------ 201 202 void ImplAnimView::ImplDraw( sal_uLong nPos ) 203 { 204 ImplDraw( nPos, NULL ); 205 } 206 207 // ------------------------------------------------------------------------ 208 209 void ImplAnimView::ImplDraw( sal_uLong nPos, VirtualDevice* pVDev ) 210 { 211 Rectangle aOutRect( mpOut->PixelToLogic( Point() ), mpOut->GetOutputSize() ); 212 213 // check, if output lies out of display 214 if( aOutRect.Intersection( Rectangle( maDispPt, maDispSz ) ).IsEmpty() ) 215 ImplSetMarked( sal_True ); 216 else if( !mbPause ) 217 { 218 VirtualDevice* pDev; 219 Point aPosPix; 220 Point aBmpPosPix; 221 Size aSizePix; 222 Size aBmpSizePix; 223 const sal_uLong nLastPos = mpParent->Count() - 1; 224 const AnimationBitmap& rAnm = mpParent->Get( (sal_uInt16) ( mnActPos = Min( nPos, nLastPos ) ) ); 225 226 ImplGetPosSize( rAnm, aPosPix, aSizePix ); 227 228 // mirrored horizontically? 229 if( mbHMirr ) 230 { 231 aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1L; 232 aBmpSizePix.Width() = -aSizePix.Width(); 233 } 234 else 235 { 236 aBmpPosPix.X() = aPosPix.X(); 237 aBmpSizePix.Width() = aSizePix.Width(); 238 } 239 240 // mirrored vertically? 241 if( mbVMirr ) 242 { 243 aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1L; 244 aBmpSizePix.Height() = -aSizePix.Height(); 245 } 246 else 247 { 248 aBmpPosPix.Y() = aPosPix.Y(); 249 aBmpSizePix.Height() = aSizePix.Height(); 250 } 251 252 // get output device 253 if( !pVDev ) 254 { 255 pDev = new VirtualDevice; 256 pDev->SetOutputSizePixel( maSzPix, sal_False ); 257 pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut ); 258 } 259 else 260 pDev = pVDev; 261 262 // restore background after each run 263 if( !nPos ) 264 { 265 meLastDisposal = DISPOSE_BACK; 266 maRestPt = Point(); 267 maRestSz = maSzPix; 268 } 269 270 // restore 271 if( ( DISPOSE_NOT != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() ) 272 { 273 if( DISPOSE_BACK == meLastDisposal ) 274 pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground ); 275 else 276 pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore ); 277 } 278 279 meLastDisposal = rAnm.eDisposal; 280 maRestPt = aPosPix; 281 maRestSz = aSizePix; 282 283 // Was muessen wir beim naechsten Mal restaurieren ? 284 // ==> ggf. in eine Bitmap stecken, ansonsten SaveBitmap 285 // aus Speichergruenden loeschen 286 if( ( meLastDisposal == DISPOSE_BACK ) || ( meLastDisposal == DISPOSE_NOT ) ) 287 mpRestore->SetOutputSizePixel( Size( 1, 1 ), sal_False ); 288 else 289 { 290 mpRestore->SetOutputSizePixel( maRestSz, sal_False ); 291 mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev ); 292 } 293 294 pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx ); 295 296 if( !pVDev ) 297 { 298 Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL; 299 300 if( pOldClip ) 301 mpOut->SetClipRegion( maClip ); 302 303 mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev ); 304 305 if( pOldClip ) 306 { 307 mpOut->SetClipRegion( *pOldClip ); 308 delete pOldClip; 309 } 310 311 delete pDev; 312 313 if( mpOut->GetOutDevType() == OUTDEV_WINDOW ) 314 ( (Window*) mpOut )->Sync(); 315 } 316 } 317 } 318 319 // ------------------------------------------------------------------------ 320 321 void ImplAnimView::ImplRepaint() 322 { 323 const sal_Bool bOldPause = mbPause; 324 325 if( mpOut->GetOutDevType() == OUTDEV_WINDOW ) 326 { 327 MapMode aTempMap( mpOut->GetMapMode() ); 328 aTempMap.SetOrigin( Point() ); 329 mpBackground->SetMapMode( aTempMap ); 330 ( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground ); 331 mpBackground->SetMapMode( MapMode() ); 332 } 333 else 334 mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut ); 335 336 mbPause = sal_False; 337 ImplDrawToPos( mnActPos ); 338 mbPause = bOldPause; 339 } 340 341 // ------------------------------------------------------------------------ 342 343 AInfo* ImplAnimView::ImplCreateAInfo() const 344 { 345 AInfo* pAInfo = new AInfo; 346 347 pAInfo->aStartOrg = maPt; 348 pAInfo->aStartSize = maSz; 349 pAInfo->pOutDev = mpOut; 350 pAInfo->pViewData = (void*) this; 351 pAInfo->nExtraData = mnExtraData; 352 pAInfo->bPause = mbPause; 353 354 return pAInfo; 355 } 356