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