xref: /trunk/main/vcl/source/gdi/impanmvw.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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