xref: /trunk/main/vcl/source/gdi/impanmvw.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include "impanmvw.hxx"
32 #include <vcl/virdev.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/salbtype.hxx>
35 
36 // ----------------
37 // - ImplAnimView -
38 // ----------------
39 
40 ImplAnimView::ImplAnimView( Animation* pParent, OutputDevice* pOut,
41 							const Point& rPt, const Size& rSz,
42 							sal_uLong nExtraData,
43 							OutputDevice* pFirstFrameOutDev ) :
44 		mpParent		( pParent ),
45 		mpOut			( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ),
46 		mnExtraData		( nExtraData ),
47 		maPt			( rPt ),
48 		maSz			( rSz ),
49 		maSzPix			( mpOut->LogicToPixel( maSz ) ),
50 		maClip			( mpOut->GetClipRegion() ),
51 		mpBackground	( new VirtualDevice ),
52 		mpRestore		( new VirtualDevice ),
53 		meLastDisposal	( DISPOSE_BACK ),
54 		mbPause			( sal_False ),
55 		mbMarked		( sal_False ),
56 		mbHMirr			( maSz.Width() < 0L ),
57 		mbVMirr			( maSz.Height() < 0L )
58 {
59 	mpParent->ImplIncAnimCount();
60 
61 	// mirrored horizontically?
62 	if( mbHMirr )
63 	{
64 		maDispPt.X() = maPt.X() + maSz.Width() + 1L;
65 		maDispSz.Width() = -maSz.Width();
66 		maSzPix.Width() = -maSzPix.Width();
67 	}
68 	else
69 	{
70 		maDispPt.X() = maPt.X();
71 		maDispSz.Width() = maSz.Width();
72 	}
73 
74 	// mirrored vertically?
75 	if( mbVMirr )
76 	{
77 		maDispPt.Y() = maPt.Y() + maSz.Height() + 1L;
78 		maDispSz.Height() = -maSz.Height();
79 		maSzPix.Height() = -maSzPix.Height();
80 	}
81 	else
82 	{
83 		maDispPt.Y() = maPt.Y();
84 		maDispSz.Height() = maSz.Height();
85 	}
86 
87 	// save background
88 	mpBackground->SetOutputSizePixel( maSzPix );
89 
90 	if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
91 	{
92 		MapMode aTempMap( mpOut->GetMapMode() );
93 		aTempMap.SetOrigin( Point() );
94 		mpBackground->SetMapMode( aTempMap );
95 		( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
96 		mpBackground->SetMapMode( MapMode() );
97 	}
98 	else
99 		mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
100 
101 	// initial drawing to actual position
102 	ImplDrawToPos( mpParent->ImplGetCurPos() );
103 
104 	// if first frame OutputDevice is set, update variables now for real OutputDevice
105 	if( pFirstFrameOutDev )
106 		maClip = ( mpOut = pOut )->GetClipRegion();
107 }
108 
109 // ------------------------------------------------------------------------
110 
111 ImplAnimView::~ImplAnimView()
112 {
113 	delete mpBackground;
114 	delete mpRestore;
115 
116 	mpParent->ImplDecAnimCount();
117 }
118 
119 // ------------------------------------------------------------------------
120 
121 sal_Bool ImplAnimView::ImplMatches( OutputDevice* pOut, long nExtraData ) const
122 {
123 	sal_Bool bRet = sal_False;
124 
125 	if( nExtraData )
126 	{
127 		if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) )
128 			bRet = sal_True;
129 	}
130 	else if( !pOut || ( pOut == mpOut ) )
131 		bRet = sal_True;
132 
133 	return bRet;
134 }
135 
136 // ------------------------------------------------------------------------
137 
138 void ImplAnimView::ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix )
139 {
140 	const Size& rAnmSize = mpParent->GetDisplaySizePixel();
141 	Point		aPt2( rAnm.aPosPix.X() + rAnm.aSizePix.Width() - 1L,
142 					  rAnm.aPosPix.Y() + rAnm.aSizePix.Height() - 1L );
143 	double		fFactX, fFactY;
144 
145 	// calculate x scaling
146 	if( rAnmSize.Width() > 1L )
147 		fFactX = (double) ( maSzPix.Width() - 1L ) / ( rAnmSize.Width() - 1L );
148 	else
149 		fFactX = 1.0;
150 
151 	// calculate y scaling
152 	if( rAnmSize.Height() > 1L )
153 		fFactY = (double) ( maSzPix.Height() - 1L ) / ( rAnmSize.Height() - 1L );
154 	else
155 		fFactY = 1.0;
156 
157 	rPosPix.X() = FRound( rAnm.aPosPix.X() * fFactX );
158 	rPosPix.Y() = FRound( rAnm.aPosPix.Y() * fFactY );
159 
160 	aPt2.X() = FRound( aPt2.X() * fFactX );
161 	aPt2.Y() = FRound( aPt2.Y() * fFactY );
162 
163 	rSizePix.Width() = aPt2.X() - rPosPix.X() + 1L;
164 	rSizePix.Height() = aPt2.Y() - rPosPix.Y() + 1L;
165 
166 	// mirrored horizontically?
167 	if( mbHMirr )
168 		rPosPix.X() = maSzPix.Width() - 1L - aPt2.X();
169 
170 	// mirrored vertically?
171 	if( mbVMirr )
172 		rPosPix.Y() = maSzPix.Height() - 1L - aPt2.Y();
173 }
174 
175 // ------------------------------------------------------------------------
176 
177 void ImplAnimView::ImplDrawToPos( sal_uLong nPos )
178 {
179 	VirtualDevice	aVDev;
180 	Region*			pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
181 
182 	aVDev.SetOutputSizePixel( maSzPix, sal_False );
183 	nPos = Min( nPos, (sal_uLong) mpParent->Count() - 1UL );
184 
185 	for( sal_uLong i = 0UL; i <= nPos; i++ )
186 		ImplDraw( i, &aVDev );
187 
188 	if( pOldClip )
189 		mpOut->SetClipRegion( maClip );
190 
191 	mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, aVDev );
192 
193 	if( pOldClip )
194 	{
195 		mpOut->SetClipRegion( *pOldClip );
196 		delete pOldClip;
197 	}
198 }
199 
200 // ------------------------------------------------------------------------
201 
202 void ImplAnimView::ImplDraw( sal_uLong nPos )
203 {
204 	ImplDraw( nPos, NULL );
205 }
206 
207 // ------------------------------------------------------------------------
208 
209 void ImplAnimView::ImplDraw( sal_uLong nPos, VirtualDevice* pVDev )
210 {
211 	Rectangle aOutRect( mpOut->PixelToLogic( Point() ), mpOut->GetOutputSize() );
212 
213 	// check, if output lies out of display
214 	if( aOutRect.Intersection( Rectangle( maDispPt, maDispSz ) ).IsEmpty() )
215 		ImplSetMarked( sal_True );
216 	else if( !mbPause )
217 	{
218 		VirtualDevice*			pDev;
219 		Point					aPosPix;
220 		Point					aBmpPosPix;
221 		Size					aSizePix;
222 		Size					aBmpSizePix;
223 		const sal_uLong				nLastPos = mpParent->Count() - 1;
224 		const AnimationBitmap&	rAnm = mpParent->Get( (sal_uInt16) ( mnActPos = Min( nPos, nLastPos ) ) );
225 
226 		ImplGetPosSize( rAnm, aPosPix, aSizePix );
227 
228 		// mirrored horizontically?
229 		if( mbHMirr )
230 		{
231 			aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1L;
232 			aBmpSizePix.Width() = -aSizePix.Width();
233 		}
234 		else
235 		{
236 			aBmpPosPix.X() = aPosPix.X();
237 			aBmpSizePix.Width() = aSizePix.Width();
238 		}
239 
240 		// mirrored vertically?
241 		if( mbVMirr )
242 		{
243 			aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1L;
244 			aBmpSizePix.Height() = -aSizePix.Height();
245 		}
246 		else
247 		{
248 			aBmpPosPix.Y() = aPosPix.Y();
249 			aBmpSizePix.Height() = aSizePix.Height();
250 		}
251 
252 		// get output device
253 		if( !pVDev )
254 		{
255 			pDev = new VirtualDevice;
256 			pDev->SetOutputSizePixel( maSzPix, sal_False );
257 			pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
258 		}
259 		else
260 			pDev = pVDev;
261 
262 		// restore background after each run
263 		if( !nPos )
264 		{
265 			meLastDisposal = DISPOSE_BACK;
266 			maRestPt = Point();
267 			maRestSz = maSzPix;
268 		}
269 
270 		// restore
271 		if( ( DISPOSE_NOT != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() )
272 		{
273 			if( DISPOSE_BACK == meLastDisposal )
274 				pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground );
275 			else
276 				pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore );
277 		}
278 
279 		meLastDisposal = rAnm.eDisposal;
280 		maRestPt = aPosPix;
281 		maRestSz = aSizePix;
282 
283 		// Was muessen wir beim naechsten Mal restaurieren ?
284 		// ==> ggf. in eine Bitmap stecken, ansonsten SaveBitmap
285 		// aus Speichergruenden loeschen
286 		if( ( meLastDisposal == DISPOSE_BACK ) || ( meLastDisposal == DISPOSE_NOT ) )
287 			mpRestore->SetOutputSizePixel( Size( 1, 1 ), sal_False );
288 		else
289 		{
290 			mpRestore->SetOutputSizePixel( maRestSz, sal_False );
291 			mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev );
292 		}
293 
294 		pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx );
295 
296 		if( !pVDev )
297 		{
298 			Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
299 
300 			if( pOldClip )
301 				mpOut->SetClipRegion( maClip );
302 
303 			mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev );
304 
305 			if( pOldClip )
306 			{
307 				mpOut->SetClipRegion( *pOldClip );
308 				delete pOldClip;
309 			}
310 
311 			delete pDev;
312 
313 			if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
314 				( (Window*) mpOut )->Sync();
315 		}
316 	}
317 }
318 
319 // ------------------------------------------------------------------------
320 
321 void ImplAnimView::ImplRepaint()
322 {
323 	const sal_Bool bOldPause = mbPause;
324 
325 	if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
326 	{
327 		MapMode aTempMap( mpOut->GetMapMode() );
328 		aTempMap.SetOrigin( Point() );
329 		mpBackground->SetMapMode( aTempMap );
330 		( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
331 		mpBackground->SetMapMode( MapMode() );
332 	}
333 	else
334 		mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
335 
336 	mbPause = sal_False;
337 	ImplDrawToPos( mnActPos );
338 	mbPause = bOldPause;
339 }
340 
341 // ------------------------------------------------------------------------
342 
343 AInfo* ImplAnimView::ImplCreateAInfo() const
344 {
345 	AInfo* pAInfo = new AInfo;
346 
347 	pAInfo->aStartOrg = maPt;
348 	pAInfo->aStartSize = maSz;
349 	pAInfo->pOutDev = mpOut;
350 	pAInfo->pViewData = (void*) this;
351 	pAInfo->nExtraData = mnExtraData;
352 	pAInfo->bPause = mbPause;
353 
354 	return pAInfo;
355 }
356