Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / source / gdi / impanmvw.cxx
blob3da968663d6eda221a86130a4930f48baa8e72e5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <memory>
21 #include "impanmvw.hxx"
23 #include <vcl/virdev.hxx>
24 #include <vcl/window.hxx>
25 #include <tools/helpers.hxx>
27 #include "window.h"
29 ImplAnimView::ImplAnimView( Animation* pParent, OutputDevice* pOut,
30 const Point& rPt, const Size& rSz,
31 sal_uLong nExtraData,
32 OutputDevice* pFirstFrameOutDev ) :
33 mpParent ( pParent ),
34 mpOut ( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ),
35 mnExtraData ( nExtraData ),
36 maPt ( rPt ),
37 maSz ( rSz ),
38 maSzPix ( mpOut->LogicToPixel( maSz ) ),
39 maClip ( mpOut->GetClipRegion() ),
40 mpBackground ( VclPtr<VirtualDevice>::Create() ),
41 mpRestore ( VclPtr<VirtualDevice>::Create() ),
42 meLastDisposal ( Disposal::Back ),
43 mbPause ( false ),
44 mbMarked ( false ),
45 mbHMirr ( maSz.Width() < 0 ),
46 mbVMirr ( maSz.Height() < 0 )
48 Animation::ImplIncAnimCount();
50 // Mirrored horizontally?
51 if( mbHMirr )
53 maDispPt.X() = maPt.X() + maSz.Width() + 1;
54 maDispSz.Width() = -maSz.Width();
55 maSzPix.Width() = -maSzPix.Width();
57 else
59 maDispPt.X() = maPt.X();
60 maDispSz.Width() = maSz.Width();
63 // Mirrored vertically?
64 if( mbVMirr )
66 maDispPt.Y() = maPt.Y() + maSz.Height() + 1;
67 maDispSz.Height() = -maSz.Height();
68 maSzPix.Height() = -maSzPix.Height();
70 else
72 maDispPt.Y() = maPt.Y();
73 maDispSz.Height() = maSz.Height();
76 // save background
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() );
87 else
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
108 bool bRet = false;
110 if( nExtraData )
112 if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) )
113 bRet = true;
115 else if( !pOut || ( pOut == mpOut ) )
116 bRet = true;
118 return bRet;
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 );
131 else
132 fFactX = 1.0;
134 // calculate y scaling
135 if( rAnmSize.Height() > 1 )
136 fFactY = (double) ( maSzPix.Height() - 1 ) / ( rAnmSize.Height() - 1 );
137 else
138 fFactY = 1.0;
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?
150 if( mbHMirr )
151 rPosPix.X() = maSzPix.Width() - 1 - aPt2.X();
153 // Mirrored vertically?
154 if( mbVMirr )
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() );
179 if (xOldClip)
180 pRenderContext->SetClipRegion( maClip );
182 pRenderContext->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *aVDev.get() );
183 if (pGuard)
184 pGuard->SetPaintRect(tools::Rectangle(maDispPt, maDispSz));
186 if (xOldClip)
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() )
206 setMarked( true );
207 else if( !mbPause )
209 VclPtr<VirtualDevice> pDev;
210 Point aPosPix;
211 Point aBmpPosPix;
212 Size aSizePix;
213 Size aBmpSizePix;
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?
220 if( mbHMirr )
222 aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1;
223 aBmpSizePix.Width() = -aSizePix.Width();
225 else
227 aBmpPosPix.X() = aPosPix.X();
228 aBmpSizePix.Width() = aSizePix.Width();
231 // Mirrored vertically?
232 if( mbVMirr )
234 aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1;
235 aBmpSizePix.Height() = -aSizePix.Height();
237 else
239 aBmpPosPix.Y() = aPosPix.Y();
240 aBmpSizePix.Height() = aSizePix.Height();
243 // get output device
244 if( !pVDev )
246 pDev = VclPtr<VirtualDevice>::Create();
247 pDev->SetOutputSizePixel( maSzPix, false );
248 pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *pRenderContext );
250 else
251 pDev = pVDev;
253 // restore background after each run
254 if( !nPos )
256 meLastDisposal = Disposal::Back;
257 maRestPt = Point();
258 maRestSz = maSzPix;
261 // restore
262 if( ( Disposal::Not != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() )
264 if( Disposal::Back == meLastDisposal )
265 pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground );
266 else
267 pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore );
270 meLastDisposal = rAnm.eDisposal;
271 maRestPt = aPosPix;
272 maRestSz = aSizePix;
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 );
279 else
281 mpRestore->SetOutputSizePixel( maRestSz, false );
282 mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev );
285 pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx );
287 if( !pVDev )
289 std::unique_ptr<vcl::Region> xOldClip(!maClip.IsNull() ? new vcl::Region( pRenderContext->GetClipRegion() ) : nullptr);
291 if (xOldClip)
292 pRenderContext->SetClipRegion( maClip );
294 pRenderContext->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev );
295 if (pGuard)
296 pGuard->SetPaintRect(tools::Rectangle(maDispPt, maDispSz));
298 if( xOldClip)
300 pRenderContext->SetClipRegion(*xOldClip);
301 xOldClip.reset();
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() );
324 else
325 mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
327 mbPause = false;
328 drawToPos( mnActPos );
329 mbPause = bOldPause;
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;
343 return pAInfo;
346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */