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