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