blob: 8c00f5b6665724c3499f445d8302b6753c2161c5 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#include "impanmvw.hxx"
#include <vcl/virdev.hxx>
#include <vcl/window.hxx>
#include <vcl/salbtype.hxx>
// ----------------
// - ImplAnimView -
// ----------------
ImplAnimView::ImplAnimView( Animation* pParent, OutputDevice* pOut,
const Point& rPt, const Size& rSz,
sal_uLong nExtraData,
OutputDevice* pFirstFrameOutDev ) :
mpParent ( pParent ),
mpOut ( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ),
mnExtraData ( nExtraData ),
maPt ( rPt ),
maSz ( rSz ),
maSzPix ( mpOut->LogicToPixel( maSz ) ),
maClip ( mpOut->GetClipRegion() ),
mpBackground ( new VirtualDevice ),
mpRestore ( new VirtualDevice ),
meLastDisposal ( DISPOSE_BACK ),
mbPause ( sal_False ),
mbMarked ( sal_False ),
mbHMirr ( maSz.Width() < 0L ),
mbVMirr ( maSz.Height() < 0L )
{
mpParent->ImplIncAnimCount();
// mirrored horizontically?
if( mbHMirr )
{
maDispPt.X() = maPt.X() + maSz.Width() + 1L;
maDispSz.Width() = -maSz.Width();
maSzPix.Width() = -maSzPix.Width();
}
else
{
maDispPt.X() = maPt.X();
maDispSz.Width() = maSz.Width();
}
// mirrored vertically?
if( mbVMirr )
{
maDispPt.Y() = maPt.Y() + maSz.Height() + 1L;
maDispSz.Height() = -maSz.Height();
maSzPix.Height() = -maSzPix.Height();
}
else
{
maDispPt.Y() = maPt.Y();
maDispSz.Height() = maSz.Height();
}
// save background
mpBackground->SetOutputSizePixel( maSzPix );
if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
{
MapMode aTempMap( mpOut->GetMapMode() );
aTempMap.SetOrigin( Point() );
mpBackground->SetMapMode( aTempMap );
( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
mpBackground->SetMapMode( MapMode() );
}
else
mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
// initial drawing to actual position
ImplDrawToPos( mpParent->ImplGetCurPos() );
// if first frame OutputDevice is set, update variables now for real OutputDevice
if( pFirstFrameOutDev )
maClip = ( mpOut = pOut )->GetClipRegion();
}
// ------------------------------------------------------------------------
ImplAnimView::~ImplAnimView()
{
delete mpBackground;
delete mpRestore;
mpParent->ImplDecAnimCount();
}
// ------------------------------------------------------------------------
sal_Bool ImplAnimView::ImplMatches( OutputDevice* pOut, long nExtraData ) const
{
sal_Bool bRet = sal_False;
if( nExtraData )
{
if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) )
bRet = sal_True;
}
else if( !pOut || ( pOut == mpOut ) )
bRet = sal_True;
return bRet;
}
// ------------------------------------------------------------------------
void ImplAnimView::ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix )
{
const Size& rAnmSize = mpParent->GetDisplaySizePixel();
Point aPt2( rAnm.aPosPix.X() + rAnm.aSizePix.Width() - 1L,
rAnm.aPosPix.Y() + rAnm.aSizePix.Height() - 1L );
double fFactX, fFactY;
// calculate x scaling
if( rAnmSize.Width() > 1L )
fFactX = (double) ( maSzPix.Width() - 1L ) / ( rAnmSize.Width() - 1L );
else
fFactX = 1.0;
// calculate y scaling
if( rAnmSize.Height() > 1L )
fFactY = (double) ( maSzPix.Height() - 1L ) / ( rAnmSize.Height() - 1L );
else
fFactY = 1.0;
rPosPix.X() = FRound( rAnm.aPosPix.X() * fFactX );
rPosPix.Y() = FRound( rAnm.aPosPix.Y() * fFactY );
aPt2.X() = FRound( aPt2.X() * fFactX );
aPt2.Y() = FRound( aPt2.Y() * fFactY );
rSizePix.Width() = aPt2.X() - rPosPix.X() + 1L;
rSizePix.Height() = aPt2.Y() - rPosPix.Y() + 1L;
// mirrored horizontically?
if( mbHMirr )
rPosPix.X() = maSzPix.Width() - 1L - aPt2.X();
// mirrored vertically?
if( mbVMirr )
rPosPix.Y() = maSzPix.Height() - 1L - aPt2.Y();
}
// ------------------------------------------------------------------------
void ImplAnimView::ImplDrawToPos( sal_uLong nPos )
{
VirtualDevice aVDev;
Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
aVDev.SetOutputSizePixel( maSzPix, sal_False );
nPos = Min( nPos, (sal_uLong) mpParent->Count() - 1UL );
for( sal_uLong i = 0UL; i <= nPos; i++ )
ImplDraw( i, &aVDev );
if( pOldClip )
mpOut->SetClipRegion( maClip );
mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, aVDev );
if( pOldClip )
{
mpOut->SetClipRegion( *pOldClip );
delete pOldClip;
}
}
// ------------------------------------------------------------------------
void ImplAnimView::ImplDraw( sal_uLong nPos )
{
ImplDraw( nPos, NULL );
}
// ------------------------------------------------------------------------
void ImplAnimView::ImplDraw( sal_uLong nPos, VirtualDevice* pVDev )
{
Rectangle aOutRect( mpOut->PixelToLogic( Point() ), mpOut->GetOutputSize() );
// check, if output lies out of display
if( aOutRect.Intersection( Rectangle( maDispPt, maDispSz ) ).IsEmpty() )
ImplSetMarked( sal_True );
else if( !mbPause )
{
VirtualDevice* pDev;
Point aPosPix;
Point aBmpPosPix;
Size aSizePix;
Size aBmpSizePix;
const sal_uLong nLastPos = mpParent->Count() - 1;
const AnimationBitmap& rAnm = mpParent->Get( (sal_uInt16) ( mnActPos = Min( nPos, nLastPos ) ) );
ImplGetPosSize( rAnm, aPosPix, aSizePix );
// mirrored horizontically?
if( mbHMirr )
{
aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1L;
aBmpSizePix.Width() = -aSizePix.Width();
}
else
{
aBmpPosPix.X() = aPosPix.X();
aBmpSizePix.Width() = aSizePix.Width();
}
// mirrored vertically?
if( mbVMirr )
{
aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1L;
aBmpSizePix.Height() = -aSizePix.Height();
}
else
{
aBmpPosPix.Y() = aPosPix.Y();
aBmpSizePix.Height() = aSizePix.Height();
}
// get output device
if( !pVDev )
{
pDev = new VirtualDevice;
pDev->SetOutputSizePixel( maSzPix, sal_False );
pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
}
else
pDev = pVDev;
// restore background after each run
if( !nPos )
{
meLastDisposal = DISPOSE_BACK;
maRestPt = Point();
maRestSz = maSzPix;
}
// restore
if( ( DISPOSE_NOT != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() )
{
if( DISPOSE_BACK == meLastDisposal )
pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground );
else
pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore );
}
meLastDisposal = rAnm.eDisposal;
maRestPt = aPosPix;
maRestSz = aSizePix;
// Was muessen wir beim naechsten Mal restaurieren ?
// ==> ggf. in eine Bitmap stecken, ansonsten SaveBitmap
// aus Speichergruenden loeschen
if( ( meLastDisposal == DISPOSE_BACK ) || ( meLastDisposal == DISPOSE_NOT ) )
mpRestore->SetOutputSizePixel( Size( 1, 1 ), sal_False );
else
{
mpRestore->SetOutputSizePixel( maRestSz, sal_False );
mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev );
}
pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx );
if( !pVDev )
{
Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
if( pOldClip )
mpOut->SetClipRegion( maClip );
mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev );
if( pOldClip )
{
mpOut->SetClipRegion( *pOldClip );
delete pOldClip;
}
delete pDev;
if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
( (Window*) mpOut )->Sync();
}
}
}
// ------------------------------------------------------------------------
void ImplAnimView::ImplRepaint()
{
const sal_Bool bOldPause = mbPause;
if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
{
MapMode aTempMap( mpOut->GetMapMode() );
aTempMap.SetOrigin( Point() );
mpBackground->SetMapMode( aTempMap );
( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
mpBackground->SetMapMode( MapMode() );
}
else
mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
mbPause = sal_False;
ImplDrawToPos( mnActPos );
mbPause = bOldPause;
}
// ------------------------------------------------------------------------
AInfo* ImplAnimView::ImplCreateAInfo() const
{
AInfo* pAInfo = new AInfo;
pAInfo->aStartOrg = maPt;
pAInfo->aStartSize = maSz;
pAInfo->pOutDev = mpOut;
pAInfo->pViewData = (void*) this;
pAInfo->nExtraData = mnExtraData;
pAInfo->bPause = mbPause;
return pAInfo;
}