1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "impanmvw.hxx"
23 #include <vcl/virdev.hxx>
24 #include <vcl/window.hxx>
25 #include <tools/helpers.hxx>
29 ImplAnimView::ImplAnimView( Animation
* pParent
, OutputDevice
* pOut
,
30 const Point
& rPt
, const Size
& rSz
,
32 OutputDevice
* pFirstFrameOutDev
) :
34 mpOut ( pFirstFrameOutDev
? pFirstFrameOutDev
: pOut
),
35 mnExtraData ( nExtraData
),
38 maSzPix ( mpOut
->LogicToPixel( maSz
) ),
39 maClip ( mpOut
->GetClipRegion() ),
40 mpBackground ( VclPtr
<VirtualDevice
>::Create() ),
41 mpRestore ( VclPtr
<VirtualDevice
>::Create() ),
42 meLastDisposal ( Disposal::Back
),
45 mbHMirr ( maSz
.Width() < 0 ),
46 mbVMirr ( maSz
.Height() < 0 )
48 Animation::ImplIncAnimCount();
50 // Mirrored horizontally?
53 maDispPt
.X() = maPt
.X() + maSz
.Width() + 1;
54 maDispSz
.Width() = -maSz
.Width();
55 maSzPix
.Width() = -maSzPix
.Width();
59 maDispPt
.X() = maPt
.X();
60 maDispSz
.Width() = maSz
.Width();
63 // Mirrored vertically?
66 maDispPt
.Y() = maPt
.Y() + maSz
.Height() + 1;
67 maDispSz
.Height() = -maSz
.Height();
68 maSzPix
.Height() = -maSzPix
.Height();
72 maDispPt
.Y() = maPt
.Y();
73 maDispSz
.Height() = maSz
.Height();
77 mpBackground
->SetOutputSizePixel( maSzPix
);
79 if( mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
81 MapMode
aTempMap( mpOut
->GetMapMode() );
82 aTempMap
.SetOrigin( Point() );
83 mpBackground
->SetMapMode( aTempMap
);
84 static_cast<vcl::Window
*>( mpOut
.get() )->SaveBackground( maDispPt
, maDispSz
, *mpBackground
);
85 mpBackground
->SetMapMode( MapMode() );
88 mpBackground
->DrawOutDev( Point(), maSzPix
, maDispPt
, maDispSz
, *mpOut
);
90 // Initialize drawing to actual position
91 drawToPos( mpParent
->ImplGetCurPos() );
93 // If first frame OutputDevice is set, update variables now for real OutputDevice
94 if( pFirstFrameOutDev
)
95 maClip
= ( mpOut
= pOut
)->GetClipRegion();
98 ImplAnimView::~ImplAnimView()
100 mpBackground
.disposeAndClear();
101 mpRestore
.disposeAndClear();
103 Animation::ImplDecAnimCount();
106 bool ImplAnimView::matches( OutputDevice
* pOut
, long nExtraData
) const
112 if( ( mnExtraData
== nExtraData
) && ( !pOut
|| ( pOut
== mpOut
) ) )
115 else if( !pOut
|| ( pOut
== mpOut
) )
121 void ImplAnimView::getPosSize( const AnimationBitmap
& rAnm
, Point
& rPosPix
, Size
& rSizePix
)
123 const Size
& rAnmSize
= mpParent
->GetDisplaySizePixel();
124 Point
aPt2( rAnm
.aPosPix
.X() + rAnm
.aSizePix
.Width() - 1,
125 rAnm
.aPosPix
.Y() + rAnm
.aSizePix
.Height() - 1 );
126 double fFactX
, fFactY
;
128 // calculate x scaling
129 if( rAnmSize
.Width() > 1 )
130 fFactX
= (double) ( maSzPix
.Width() - 1 ) / ( rAnmSize
.Width() - 1 );
134 // calculate y scaling
135 if( rAnmSize
.Height() > 1 )
136 fFactY
= (double) ( maSzPix
.Height() - 1 ) / ( rAnmSize
.Height() - 1 );
140 rPosPix
.X() = FRound( rAnm
.aPosPix
.X() * fFactX
);
141 rPosPix
.Y() = FRound( rAnm
.aPosPix
.Y() * fFactY
);
143 aPt2
.X() = FRound( aPt2
.X() * fFactX
);
144 aPt2
.Y() = FRound( aPt2
.Y() * fFactY
);
146 rSizePix
.Width() = aPt2
.X() - rPosPix
.X() + 1;
147 rSizePix
.Height() = aPt2
.Y() - rPosPix
.Y() + 1;
149 // Mirrored horizontally?
151 rPosPix
.X() = maSzPix
.Width() - 1 - aPt2
.X();
153 // Mirrored vertically?
155 rPosPix
.Y() = maSzPix
.Height() - 1 - aPt2
.Y();
158 void ImplAnimView::drawToPos( sal_uLong nPos
)
160 VclPtr
<vcl::RenderContext
> pRenderContext
= mpOut
;
162 std::unique_ptr
<PaintBufferGuard
> pGuard
;
163 if (mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
165 vcl::Window
* pWindow
= static_cast<vcl::Window
*>(mpOut
.get());
166 pGuard
.reset(new PaintBufferGuard(pWindow
->ImplGetWindowImpl()->mpFrameData
, pWindow
));
167 pRenderContext
= pGuard
->GetRenderContext();
170 ScopedVclPtrInstance
<VirtualDevice
> aVDev
;
171 std::unique_ptr
<vcl::Region
> xOldClip(!maClip
.IsNull() ? new vcl::Region( pRenderContext
->GetClipRegion() ) : nullptr);
173 aVDev
->SetOutputSizePixel( maSzPix
, false );
174 nPos
= std::min( nPos
, (sal_uLong
) mpParent
->Count() - 1UL );
176 for( sal_uLong i
= 0UL; i
<= nPos
; i
++ )
177 draw( i
, aVDev
.get() );
180 pRenderContext
->SetClipRegion( maClip
);
182 pRenderContext
->DrawOutDev( maDispPt
, maDispSz
, Point(), maSzPix
, *aVDev
.get() );
184 pGuard
->SetPaintRect(tools::Rectangle(maDispPt
, maDispSz
));
187 pRenderContext
->SetClipRegion(*xOldClip
);
190 void ImplAnimView::draw( sal_uLong nPos
, VirtualDevice
* pVDev
)
192 VclPtr
<vcl::RenderContext
> pRenderContext
= mpOut
;
194 std::unique_ptr
<PaintBufferGuard
> pGuard
;
195 if (!pVDev
&& mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
197 vcl::Window
* pWindow
= static_cast<vcl::Window
*>(mpOut
.get());
198 pGuard
.reset(new PaintBufferGuard(pWindow
->ImplGetWindowImpl()->mpFrameData
, pWindow
));
199 pRenderContext
= pGuard
->GetRenderContext();
202 tools::Rectangle
aOutRect( pRenderContext
->PixelToLogic( Point() ), pRenderContext
->GetOutputSize() );
204 // check, if output lies out of display
205 if( aOutRect
.Intersection( tools::Rectangle( maDispPt
, maDispSz
) ).IsEmpty() )
209 VclPtr
<VirtualDevice
> pDev
;
214 const sal_uLong nLastPos
= mpParent
->Count() - 1;
215 const AnimationBitmap
& rAnm
= mpParent
->Get( (sal_uInt16
) ( mnActPos
= std::min( nPos
, nLastPos
) ) );
217 getPosSize( rAnm
, aPosPix
, aSizePix
);
219 // Mirrored horizontally?
222 aBmpPosPix
.X() = aPosPix
.X() + aSizePix
.Width() - 1;
223 aBmpSizePix
.Width() = -aSizePix
.Width();
227 aBmpPosPix
.X() = aPosPix
.X();
228 aBmpSizePix
.Width() = aSizePix
.Width();
231 // Mirrored vertically?
234 aBmpPosPix
.Y() = aPosPix
.Y() + aSizePix
.Height() - 1;
235 aBmpSizePix
.Height() = -aSizePix
.Height();
239 aBmpPosPix
.Y() = aPosPix
.Y();
240 aBmpSizePix
.Height() = aSizePix
.Height();
246 pDev
= VclPtr
<VirtualDevice
>::Create();
247 pDev
->SetOutputSizePixel( maSzPix
, false );
248 pDev
->DrawOutDev( Point(), maSzPix
, maDispPt
, maDispSz
, *pRenderContext
);
253 // restore background after each run
256 meLastDisposal
= Disposal::Back
;
262 if( ( Disposal::Not
!= meLastDisposal
) && maRestSz
.Width() && maRestSz
.Height() )
264 if( Disposal::Back
== meLastDisposal
)
265 pDev
->DrawOutDev( maRestPt
, maRestSz
, maRestPt
, maRestSz
, *mpBackground
);
267 pDev
->DrawOutDev( maRestPt
, maRestSz
, Point(), maRestSz
, *mpRestore
);
270 meLastDisposal
= rAnm
.eDisposal
;
274 // What do we need to restore the next time?
275 // Put it into a bitmap if needed, else delete
276 // SaveBitmap to conserve memory
277 if( ( meLastDisposal
== Disposal::Back
) || ( meLastDisposal
== Disposal::Not
) )
278 mpRestore
->SetOutputSizePixel( Size( 1, 1 ), false );
281 mpRestore
->SetOutputSizePixel( maRestSz
, false );
282 mpRestore
->DrawOutDev( Point(), maRestSz
, aPosPix
, aSizePix
, *pDev
);
285 pDev
->DrawBitmapEx( aBmpPosPix
, aBmpSizePix
, rAnm
.aBmpEx
);
289 std::unique_ptr
<vcl::Region
> xOldClip(!maClip
.IsNull() ? new vcl::Region( pRenderContext
->GetClipRegion() ) : nullptr);
292 pRenderContext
->SetClipRegion( maClip
);
294 pRenderContext
->DrawOutDev( maDispPt
, maDispSz
, Point(), maSzPix
, *pDev
);
296 pGuard
->SetPaintRect(tools::Rectangle(maDispPt
, maDispSz
));
300 pRenderContext
->SetClipRegion(*xOldClip
);
304 pDev
.disposeAndClear();
306 if( pRenderContext
->GetOutDevType() == OUTDEV_WINDOW
)
307 static_cast<vcl::Window
*>( pRenderContext
.get() )->Flush();
312 void ImplAnimView::repaint()
314 const bool bOldPause
= mbPause
;
316 if( mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
318 MapMode
aTempMap( mpOut
->GetMapMode() );
319 aTempMap
.SetOrigin( Point() );
320 mpBackground
->SetMapMode( aTempMap
);
321 static_cast<vcl::Window
*>( mpOut
.get() )->SaveBackground( maDispPt
, maDispSz
, *mpBackground
);
322 mpBackground
->SetMapMode( MapMode() );
325 mpBackground
->DrawOutDev( Point(), maSzPix
, maDispPt
, maDispSz
, *mpOut
);
328 drawToPos( mnActPos
);
332 AInfo
* ImplAnimView::createAInfo() const
334 AInfo
* pAInfo
= new AInfo
;
336 pAInfo
->aStartOrg
= maPt
;
337 pAInfo
->aStartSize
= maSz
;
338 pAInfo
->pOutDev
= mpOut
;
339 pAInfo
->pViewData
= const_cast<ImplAnimView
*>(this);
340 pAInfo
->nExtraData
= mnExtraData
;
341 pAInfo
->bPause
= mbPause
;
346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */