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 <vcl/virdev.hxx>
22 #include <vcl/window.hxx>
23 #include <tools/helpers.hxx>
25 #include "impanmvw.hxx"
27 ImplAnimView::ImplAnimView( Animation
* pParent
, OutputDevice
* pOut
,
28 const Point
& rPt
, const Size
& rSz
,
30 OutputDevice
* pFirstFrameOutDev
) :
32 mpOut ( pFirstFrameOutDev
? pFirstFrameOutDev
: pOut
),
33 mnExtraData ( nExtraData
),
36 maSzPix ( mpOut
->LogicToPixel( maSz
) ),
37 maClip ( mpOut
->GetClipRegion() ),
38 mpBackground ( VclPtr
<VirtualDevice
>::Create() ),
39 mpRestore ( VclPtr
<VirtualDevice
>::Create() ),
40 meLastDisposal ( Disposal::Back
),
43 mbHMirr ( maSz
.Width() < 0L ),
44 mbVMirr ( maSz
.Height() < 0L )
46 Animation::ImplIncAnimCount();
48 // Mirrored horizontally?
51 maDispPt
.X() = maPt
.X() + maSz
.Width() + 1L;
52 maDispSz
.Width() = -maSz
.Width();
53 maSzPix
.Width() = -maSzPix
.Width();
57 maDispPt
.X() = maPt
.X();
58 maDispSz
.Width() = maSz
.Width();
61 // Mirrored vertically?
64 maDispPt
.Y() = maPt
.Y() + maSz
.Height() + 1L;
65 maDispSz
.Height() = -maSz
.Height();
66 maSzPix
.Height() = -maSzPix
.Height();
70 maDispPt
.Y() = maPt
.Y();
71 maDispSz
.Height() = maSz
.Height();
75 mpBackground
->SetOutputSizePixel( maSzPix
);
77 if( mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
79 MapMode
aTempMap( mpOut
->GetMapMode() );
80 aTempMap
.SetOrigin( Point() );
81 mpBackground
->SetMapMode( aTempMap
);
82 static_cast<vcl::Window
*>( mpOut
.get() )->SaveBackground( maDispPt
, maDispSz
, Point(), *mpBackground
);
83 mpBackground
->SetMapMode( MapMode() );
86 mpBackground
->DrawOutDev( Point(), maSzPix
, maDispPt
, maDispSz
, *mpOut
);
88 // Initialize drawing to actual position
89 drawToPos( mpParent
->ImplGetCurPos() );
91 // If first frame OutputDevice is set, update variables now for real OutputDevice
92 if( pFirstFrameOutDev
)
93 maClip
= ( mpOut
= pOut
)->GetClipRegion();
96 ImplAnimView::~ImplAnimView()
98 mpBackground
.disposeAndClear();
99 mpRestore
.disposeAndClear();
101 Animation::ImplDecAnimCount();
104 bool ImplAnimView::matches( OutputDevice
* pOut
, long nExtraData
) const
110 if( ( mnExtraData
== nExtraData
) && ( !pOut
|| ( pOut
== mpOut
) ) )
113 else if( !pOut
|| ( pOut
== mpOut
) )
119 void ImplAnimView::getPosSize( const AnimationBitmap
& rAnm
, Point
& rPosPix
, Size
& rSizePix
)
121 const Size
& rAnmSize
= mpParent
->GetDisplaySizePixel();
122 Point
aPt2( rAnm
.aPosPix
.X() + rAnm
.aSizePix
.Width() - 1L,
123 rAnm
.aPosPix
.Y() + rAnm
.aSizePix
.Height() - 1L );
124 double fFactX
, fFactY
;
126 // calculate x scaling
127 if( rAnmSize
.Width() > 1L )
128 fFactX
= (double) ( maSzPix
.Width() - 1L ) / ( rAnmSize
.Width() - 1L );
132 // calculate y scaling
133 if( rAnmSize
.Height() > 1L )
134 fFactY
= (double) ( maSzPix
.Height() - 1L ) / ( rAnmSize
.Height() - 1L );
138 rPosPix
.X() = FRound( rAnm
.aPosPix
.X() * fFactX
);
139 rPosPix
.Y() = FRound( rAnm
.aPosPix
.Y() * fFactY
);
141 aPt2
.X() = FRound( aPt2
.X() * fFactX
);
142 aPt2
.Y() = FRound( aPt2
.Y() * fFactY
);
144 rSizePix
.Width() = aPt2
.X() - rPosPix
.X() + 1L;
145 rSizePix
.Height() = aPt2
.Y() - rPosPix
.Y() + 1L;
147 // Mirrored horizontally?
149 rPosPix
.X() = maSzPix
.Width() - 1L - aPt2
.X();
151 // Mirrored vertically?
153 rPosPix
.Y() = maSzPix
.Height() - 1L - aPt2
.Y();
156 void ImplAnimView::drawToPos( sal_uLong nPos
)
158 VclPtr
<vcl::RenderContext
> pRenderContext
= mpOut
;
160 std::unique_ptr
<PaintBufferGuard
> pGuard
;
161 if (mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
163 vcl::Window
* pWindow
= static_cast<vcl::Window
*>(mpOut
.get());
164 pGuard
.reset(new PaintBufferGuard(pWindow
->ImplGetWindowImpl()->mpFrameData
, pWindow
));
165 pRenderContext
= pGuard
->GetRenderContext();
168 ScopedVclPtrInstance
<VirtualDevice
> aVDev
;
169 std::unique_ptr
<vcl::Region
> xOldClip(!maClip
.IsNull() ? new vcl::Region( pRenderContext
->GetClipRegion() ) : nullptr);
171 aVDev
->SetOutputSizePixel( maSzPix
, false );
172 nPos
= std::min( nPos
, (sal_uLong
) mpParent
->Count() - 1UL );
174 for( sal_uLong i
= 0UL; i
<= nPos
; i
++ )
175 draw( i
, aVDev
.get() );
178 pRenderContext
->SetClipRegion( maClip
);
180 pRenderContext
->DrawOutDev( maDispPt
, maDispSz
, Point(), maSzPix
, *aVDev
.get() );
182 pGuard
->SetPaintRect(Rectangle(maDispPt
, maDispSz
));
185 pRenderContext
->SetClipRegion(*xOldClip
);
188 void ImplAnimView::draw( sal_uLong nPos
, VirtualDevice
* pVDev
)
190 VclPtr
<vcl::RenderContext
> pRenderContext
= mpOut
;
192 std::unique_ptr
<PaintBufferGuard
> pGuard
;
193 if (!pVDev
&& mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
195 vcl::Window
* pWindow
= static_cast<vcl::Window
*>(mpOut
.get());
196 pGuard
.reset(new PaintBufferGuard(pWindow
->ImplGetWindowImpl()->mpFrameData
, pWindow
));
197 pRenderContext
= pGuard
->GetRenderContext();
200 Rectangle
aOutRect( pRenderContext
->PixelToLogic( Point() ), pRenderContext
->GetOutputSize() );
202 // check, if output lies out of display
203 if( aOutRect
.Intersection( Rectangle( maDispPt
, maDispSz
) ).IsEmpty() )
207 VclPtr
<VirtualDevice
> pDev
;
212 const sal_uLong nLastPos
= mpParent
->Count() - 1;
213 const AnimationBitmap
& rAnm
= mpParent
->Get( (sal_uInt16
) ( mnActPos
= std::min( nPos
, nLastPos
) ) );
215 getPosSize( rAnm
, aPosPix
, aSizePix
);
217 // Mirrored horizontally?
220 aBmpPosPix
.X() = aPosPix
.X() + aSizePix
.Width() - 1L;
221 aBmpSizePix
.Width() = -aSizePix
.Width();
225 aBmpPosPix
.X() = aPosPix
.X();
226 aBmpSizePix
.Width() = aSizePix
.Width();
229 // Mirrored vertically?
232 aBmpPosPix
.Y() = aPosPix
.Y() + aSizePix
.Height() - 1L;
233 aBmpSizePix
.Height() = -aSizePix
.Height();
237 aBmpPosPix
.Y() = aPosPix
.Y();
238 aBmpSizePix
.Height() = aSizePix
.Height();
244 pDev
= VclPtr
<VirtualDevice
>::Create();
245 pDev
->SetOutputSizePixel( maSzPix
, false );
246 pDev
->DrawOutDev( Point(), maSzPix
, maDispPt
, maDispSz
, *pRenderContext
);
251 // restore background after each run
254 meLastDisposal
= Disposal::Back
;
260 if( ( Disposal::Not
!= meLastDisposal
) && maRestSz
.Width() && maRestSz
.Height() )
262 if( Disposal::Back
== meLastDisposal
)
263 pDev
->DrawOutDev( maRestPt
, maRestSz
, maRestPt
, maRestSz
, *mpBackground
);
265 pDev
->DrawOutDev( maRestPt
, maRestSz
, Point(), maRestSz
, *mpRestore
);
268 meLastDisposal
= rAnm
.eDisposal
;
272 // What do we need to restore the next time?
273 // Put it into a bitmap if needed, else delete
274 // SaveBitmap to conserve memory
275 if( ( meLastDisposal
== Disposal::Back
) || ( meLastDisposal
== Disposal::Not
) )
276 mpRestore
->SetOutputSizePixel( Size( 1, 1 ), false );
279 mpRestore
->SetOutputSizePixel( maRestSz
, false );
280 mpRestore
->DrawOutDev( Point(), maRestSz
, aPosPix
, aSizePix
, *pDev
);
283 pDev
->DrawBitmapEx( aBmpPosPix
, aBmpSizePix
, rAnm
.aBmpEx
);
287 std::unique_ptr
<vcl::Region
> xOldClip(!maClip
.IsNull() ? new vcl::Region( pRenderContext
->GetClipRegion() ) : nullptr);
290 pRenderContext
->SetClipRegion( maClip
);
292 pRenderContext
->DrawOutDev( maDispPt
, maDispSz
, Point(), maSzPix
, *pDev
);
294 pGuard
->SetPaintRect(Rectangle(maDispPt
, maDispSz
));
298 pRenderContext
->SetClipRegion(*xOldClip
);
302 pDev
.disposeAndClear();
304 if( pRenderContext
->GetOutDevType() == OUTDEV_WINDOW
)
305 static_cast<vcl::Window
*>( pRenderContext
.get() )->Flush();
310 void ImplAnimView::repaint()
312 const bool bOldPause
= mbPause
;
314 if( mpOut
->GetOutDevType() == OUTDEV_WINDOW
)
316 MapMode
aTempMap( mpOut
->GetMapMode() );
317 aTempMap
.SetOrigin( Point() );
318 mpBackground
->SetMapMode( aTempMap
);
319 static_cast<vcl::Window
*>( mpOut
.get() )->SaveBackground( maDispPt
, maDispSz
, Point(), *mpBackground
);
320 mpBackground
->SetMapMode( MapMode() );
323 mpBackground
->DrawOutDev( Point(), maSzPix
, maDispPt
, maDispSz
, *mpOut
);
326 drawToPos( mnActPos
);
330 AInfo
* ImplAnimView::createAInfo() const
332 AInfo
* pAInfo
= new AInfo
;
334 pAInfo
->aStartOrg
= maPt
;
335 pAInfo
->aStartSize
= maSz
;
336 pAInfo
->pOutDev
= mpOut
;
337 pAInfo
->pViewData
= const_cast<ImplAnimView
*>(this);
338 pAInfo
->nExtraData
= mnExtraData
;
339 pAInfo
->bPause
= mbPause
;
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */