Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / vcl / source / gdi / impanmvw.cxx
blob2606283c5cd6cc77157b8113d8beec2d3f913ea4
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 <window.h>
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,
29 sal_uLong nExtraData,
30 OutputDevice* pFirstFrameOutDev ) :
31 mpParent ( pParent ),
32 mpOut ( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ),
33 mnExtraData ( nExtraData ),
34 maPt ( rPt ),
35 maSz ( rSz ),
36 maSzPix ( mpOut->LogicToPixel( maSz ) ),
37 maClip ( mpOut->GetClipRegion() ),
38 mpBackground ( VclPtr<VirtualDevice>::Create() ),
39 mpRestore ( VclPtr<VirtualDevice>::Create() ),
40 meLastDisposal ( Disposal::Back ),
41 mbPause ( false ),
42 mbMarked ( false ),
43 mbHMirr ( maSz.Width() < 0L ),
44 mbVMirr ( maSz.Height() < 0L )
46 Animation::ImplIncAnimCount();
48 // Mirrored horizontally?
49 if( mbHMirr )
51 maDispPt.X() = maPt.X() + maSz.Width() + 1L;
52 maDispSz.Width() = -maSz.Width();
53 maSzPix.Width() = -maSzPix.Width();
55 else
57 maDispPt.X() = maPt.X();
58 maDispSz.Width() = maSz.Width();
61 // Mirrored vertically?
62 if( mbVMirr )
64 maDispPt.Y() = maPt.Y() + maSz.Height() + 1L;
65 maDispSz.Height() = -maSz.Height();
66 maSzPix.Height() = -maSzPix.Height();
68 else
70 maDispPt.Y() = maPt.Y();
71 maDispSz.Height() = maSz.Height();
74 // save background
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() );
85 else
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
106 bool bRet = false;
108 if( nExtraData )
110 if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) )
111 bRet = true;
113 else if( !pOut || ( pOut == mpOut ) )
114 bRet = true;
116 return bRet;
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 );
129 else
130 fFactX = 1.0;
132 // calculate y scaling
133 if( rAnmSize.Height() > 1L )
134 fFactY = (double) ( maSzPix.Height() - 1L ) / ( rAnmSize.Height() - 1L );
135 else
136 fFactY = 1.0;
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?
148 if( mbHMirr )
149 rPosPix.X() = maSzPix.Width() - 1L - aPt2.X();
151 // Mirrored vertically?
152 if( mbVMirr )
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() );
177 if (xOldClip)
178 pRenderContext->SetClipRegion( maClip );
180 pRenderContext->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *aVDev.get() );
181 if (pGuard)
182 pGuard->SetPaintRect(Rectangle(maDispPt, maDispSz));
184 if (xOldClip)
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() )
204 setMarked( true );
205 else if( !mbPause )
207 VclPtr<VirtualDevice> pDev;
208 Point aPosPix;
209 Point aBmpPosPix;
210 Size aSizePix;
211 Size aBmpSizePix;
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?
218 if( mbHMirr )
220 aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1L;
221 aBmpSizePix.Width() = -aSizePix.Width();
223 else
225 aBmpPosPix.X() = aPosPix.X();
226 aBmpSizePix.Width() = aSizePix.Width();
229 // Mirrored vertically?
230 if( mbVMirr )
232 aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1L;
233 aBmpSizePix.Height() = -aSizePix.Height();
235 else
237 aBmpPosPix.Y() = aPosPix.Y();
238 aBmpSizePix.Height() = aSizePix.Height();
241 // get output device
242 if( !pVDev )
244 pDev = VclPtr<VirtualDevice>::Create();
245 pDev->SetOutputSizePixel( maSzPix, false );
246 pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *pRenderContext );
248 else
249 pDev = pVDev;
251 // restore background after each run
252 if( !nPos )
254 meLastDisposal = Disposal::Back;
255 maRestPt = Point();
256 maRestSz = maSzPix;
259 // restore
260 if( ( Disposal::Not != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() )
262 if( Disposal::Back == meLastDisposal )
263 pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground );
264 else
265 pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore );
268 meLastDisposal = rAnm.eDisposal;
269 maRestPt = aPosPix;
270 maRestSz = aSizePix;
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 );
277 else
279 mpRestore->SetOutputSizePixel( maRestSz, false );
280 mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev );
283 pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx );
285 if( !pVDev )
287 std::unique_ptr<vcl::Region> xOldClip(!maClip.IsNull() ? new vcl::Region( pRenderContext->GetClipRegion() ) : nullptr);
289 if (xOldClip)
290 pRenderContext->SetClipRegion( maClip );
292 pRenderContext->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev );
293 if (pGuard)
294 pGuard->SetPaintRect(Rectangle(maDispPt, maDispSz));
296 if( xOldClip)
298 pRenderContext->SetClipRegion(*xOldClip);
299 xOldClip.reset();
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() );
322 else
323 mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
325 mbPause = false;
326 drawToPos( mnActPos );
327 mbPause = bOldPause;
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;
341 return pAInfo;
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */