source: trunk/src/helpers/animate.c@ 15

Last change on this file since 15 was 15, checked in by umoeller, 25 years ago

Coupla bugfixes.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1
2/*
3 *@@sourcefile animate.c:
4 * contains a bit of helper code for animations.
5 *
6 * This is a new file with V0.81. Most of this code used to reside
7 * in common.c with previous versions.
8 * Note that with V0.9.0, the code for icon animations has been
9 * moved to the new comctl.c file.
10 *
11 * Usage: All PM programs.
12 *
13 * Function prefixes (new with V0.81):
14 * -- anm* Animation helper functions
15 *
16 * Note: Version numbering in this file relates to XWorkplace version
17 * numbering.
18 *
19 *@@header "helpers\animate.h"
20 */
21
22/*
23 * Copyright (C) 1997-2000 Ulrich M”ller.
24 * This file is part of the "XWorkplace helpers" source package.
25 * This is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published
27 * by the Free Software Foundation, in version 2 as it comes in the
28 * "COPYING" file of the XWorkplace main distribution.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 */
34
35#define OS2EMX_PLAIN_CHAR
36 // this is needed for "os2emx.h"; if this is defined,
37 // emx will define PSZ as _signed_ char, otherwise
38 // as unsigned char
39
40#define INCL_DOSPROCESS
41#define INCL_DOSDEVICES
42#define INCL_DOSDEVIOCTL
43#define INCL_DOSMISC
44#define INCL_DOSERRORS
45
46#define INCL_WINPOINTERS
47#define INCL_WINSYS
48
49#define INCL_GPILOGCOLORTABLE
50#define INCL_GPIPRIMITIVES
51#define INCL_GPIBITMAPS // added UM 99-10-22; needed for EMX headers
52#include <os2.h>
53
54#include <stdlib.h>
55#include <string.h>
56
57#include "setup.h" // code generation and debugging options
58
59#include "helpers\animate.h"
60
61#include "helpers\winh.h"
62#include "helpers\gpih.h"
63
64/*
65 *@@category: Helpers\PM helpers\Animation helpers
66 */
67
68/*
69 *@@ anmBlowUpBitmap:
70 * this displays an animation based on a given bitmap.
71 * The bitmap is "blown up" in that it is continually
72 * increased in size until the original size is reached.
73 * The animation is calculated so that it lasts exactly
74 * ulAnimation milliseconds, no matter how fast the
75 * system is.
76 *
77 * This function does not return until the animation
78 * has completed.
79 *
80 * You should run this routine in a thread with higher-
81 * than-normal priority, because otherwise the kernel
82 * might interrupt the thread, causing a somewhat jerky
83 * display.
84 *
85 * Returns the count of animation steps that were drawn.
86 * This is dependent on the speed of the system.
87 *
88 *@@changed V0.9.7 (2000-12-08) [umoeller]: got rid of dtGetULongTime
89 */
90
91BOOL anmBlowUpBitmap(HPS hps, // in: from WinGetScreenPS(HWND_DESKTOP)
92 HBITMAP hbm, // in: bitmap to be displayed
93 ULONG ulAnimationTime) // in: total animation time (ms)
94{
95 ULONG ulrc = 0;
96 ULONG ulInitialTime,
97 ulNowTime;
98 // ulCurrentSize = 10;
99
100 if (hps)
101 {
102 POINTL ptl = {0, 0};
103 RECTL rtlStretch;
104 ULONG ul,
105 ulSteps = 20;
106 BITMAPINFOHEADER bih;
107 GpiQueryBitmapParameters(hbm, &bih);
108 /* ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)
109 - BMPSPACING
110 - bih.cy; */
111 ptl.x = (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)
112 - bih.cx) / 2;
113 ptl.y = (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)
114 - bih.cy) / 2;
115
116 // we now use ul for the current animation step,
117 // which is a pointer on a scale from 1 to ulAnimationTime;
118 // ul will be recalculated after each animation
119 // step according to how much time the animation
120 // has cost on this display so far. This has the
121 // following advantages:
122 // 1) no matter how fast the system is, the animation
123 // will always last ulAnimationTime milliseconds
124 // 2) since large bitmaps take more time to calculate,
125 // the animation won't appear to slow down then
126 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
127 &ulInitialTime,
128 sizeof(ulInitialTime));
129 ul = 1;
130 ulSteps = 1000;
131 do {
132 LONG cx = (((bih.cx-20) * ul) / ulSteps) + 20;
133 LONG cy = (((bih.cy-20) * ul) / ulSteps) + 20;
134 rtlStretch.xLeft = ptl.x + ((bih.cx - cx) / 2);
135 rtlStretch.yBottom = ptl.y + ((bih.cy - cy) / 2);
136 rtlStretch.xRight = rtlStretch.xLeft + cx;
137 rtlStretch.yTop = rtlStretch.yBottom + cy;
138
139 WinDrawBitmap(hps, hbm, NULL, (PPOINTL)&rtlStretch,
140 0, 0, // we don't need colors
141 DBM_STRETCH);
142
143 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
144 &ulNowTime,
145 sizeof(ulNowTime));
146
147 // recalculate ul: rule of three based on the
148 // time we've spent on animation so far
149 ul = (ulSteps
150 * (ulNowTime - ulInitialTime)) // time spent so far
151 / ulAnimationTime; // time to spend altogether
152
153 ulrc++; // return count
154
155 } while (ul < ulSteps);
156
157 // finally, draw the 1:1 version
158 WinDrawBitmap(hps, hbm, NULL, &ptl,
159 0, 0, // we don't need colors
160 DBM_NORMAL);
161
162 } // end if (hps)
163
164 return (ulrc);
165}
166
167#define LAST_WIDTH 2
168#define LAST_STEPS 50
169#define WAIT_TIME 10
170
171/* ******************************************************************
172 *
173 * Other animations
174 *
175 ********************************************************************/
176
177/*
178 *@@ anmPowerOff:
179 * displays an animation that looks like a
180 * monitor being turned off; hps must have
181 * been acquired using WinGetScreenPS,
182 * ulSteps should be around 40-50.
183 *
184 *@@changed V0.9.7 (2000-12-08) [umoeller]: got rid of dtGetULongTime
185 */
186
187VOID anmPowerOff(HPS hps, ULONG ulSteps)
188{
189 RECTL rclScreen, rclNow, rclLast, rclDraw;
190 ULONG ul = ulSteps;
191 ULONG ulPhase = 1;
192
193 WinQueryWindowRect(HWND_DESKTOP, &rclScreen);
194
195 WinShowPointer(HWND_DESKTOP, FALSE);
196
197 memcpy(&rclLast, &rclScreen, sizeof(RECTL));
198
199 // In order to draw the animation, we tell apart three
200 // "phases", signified by the ulPhase variable. While
201 // ulPhase != 99, we stay in a do-while loop.
202 ul = 0;
203 ulPhase = 1;
204
205 do
206 {
207 ULONG ulFromTime, ulTime2;
208 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
209 &ulFromTime,
210 sizeof(ulFromTime));
211
212 if (ulPhase == 1)
213 {
214 // Phase 1: "shrink" the screen by drawing black
215 // rectangles from the edges towards the center
216 // of the screen. With every loop, we draw the
217 // rectangles a bit closer to the center, until
218 // the center is black too. Sort of like this:
219
220 // ***************************
221 // * black *
222 // * *
223 // * ............. *
224 // * . rclNow: . *
225 // * -> . untouched . <- *
226 // * ............. *
227 // * ^ *
228 // * ! *
229 // ***************************
230
231 // rclNow contains the rectangle _around_ which
232 // the black rectangles are to be drawn. With
233 // every iteration, rclNow is reduced in size.
234 rclNow.xLeft = ((rclScreen.yTop / 2) * ul / ulSteps );
235 rclNow.xRight = (rclScreen.xRight) - rclNow.xLeft;
236 rclNow.yBottom = ((rclScreen.yTop / 2) * ul / ulSteps );
237 rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom;
238
239 if (rclNow.yBottom > (rclNow.yTop - LAST_WIDTH) )
240 {
241 rclNow.yBottom = (rclScreen.yTop / 2) - LAST_WIDTH;
242 rclNow.yTop = (rclScreen.yTop / 2) + LAST_WIDTH;
243 }
244
245 // draw black rectangle on top of rclNow
246 rclDraw.xLeft = rclLast.xLeft;
247 rclDraw.xRight = rclLast.xRight;
248 rclDraw.yBottom = rclNow.yTop;
249 rclDraw.yTop = rclLast.yTop;
250 WinFillRect(hps, &rclDraw, CLR_BLACK);
251
252 // draw black rectangle left of rclNow
253 rclDraw.xLeft = rclLast.xLeft;
254 rclDraw.xRight = rclNow.xLeft;
255 rclDraw.yBottom = rclLast.yBottom;
256 rclDraw.yTop = rclLast.yTop;
257 WinFillRect(hps, &rclDraw, CLR_BLACK);
258
259 // draw black rectangle right of rclNow
260 rclDraw.xLeft = rclNow.xRight;
261 rclDraw.xRight = rclLast.xRight;
262 rclDraw.yBottom = rclLast.yBottom;
263 rclDraw.yTop = rclLast.yTop;
264 WinFillRect(hps, &rclDraw, CLR_BLACK);
265
266 // draw black rectangle at the bottom of rclNow
267 rclDraw.xLeft = rclLast.xLeft;
268 rclDraw.xRight = rclLast.xRight;
269 rclDraw.yBottom = rclLast.yBottom;
270 rclDraw.yTop = rclNow.yBottom;
271 WinFillRect(hps, &rclDraw, CLR_BLACK);
272
273 // remember rclNow for next iteration
274 memcpy(&rclLast, &rclNow, sizeof(RECTL));
275
276 // done with "shrinking"?
277 if ( rclNow.xRight < ((rclScreen.xRight / 2) + LAST_WIDTH) )
278 ulPhase = 2; // exit
279 }
280 else if (ulPhase == 2)
281 {
282 // Phase 2: draw a horizontal white line about
283 // where the last rclNow was. This is only
284 // executed once.
285
286 // ***************************
287 // * black *
288 // * *
289 // * *
290 // * ----------- *
291 // * *
292 // * *
293 // * *
294 // ***************************
295
296 rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
297 rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
298 rclDraw.yBottom = (rclScreen.yTop * 1 / 4);
299 rclDraw.yTop = (rclScreen.yTop * 3 / 4);
300 WinFillRect(hps, &rclDraw, CLR_WHITE);
301
302 ulPhase = 3;
303 ul = 0;
304
305 }
306 else if (ulPhase == 3)
307 {
308 // Phase 3: make the white line shorter with
309 // every iteration by drawing black rectangles
310 // above it. These are drawn closer to the
311 // center with each iteration.
312
313 // ***************************
314 // * black *
315 // * *
316 // * *
317 // * -> ---- <- *
318 // * *
319 // * *
320 // * *
321 // ***************************
322
323 rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
324 rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
325 rclDraw.yTop = (rclScreen.yTop * 3 / 4);
326 rclDraw.yBottom = (rclScreen.yTop * 3 / 4) - ((rclScreen.yTop * 1 / 4) * ul / LAST_STEPS);
327 if (rclDraw.yBottom < ((rclScreen.yTop / 2) + LAST_WIDTH))
328 rclDraw.yBottom = ((rclScreen.yTop / 2) + LAST_WIDTH);
329 WinFillRect(hps, &rclDraw, CLR_BLACK);
330
331 rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
332 rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
333 rclDraw.yBottom = (rclScreen.yTop * 1 / 4);
334 rclDraw.yTop = (rclScreen.yTop * 1 / 4) + ((rclScreen.yTop * 1 / 4) * ul / LAST_STEPS);
335 if (rclDraw.yTop > ((rclScreen.yTop / 2) - LAST_WIDTH))
336 rclDraw.yBottom = ((rclScreen.yTop / 2) - LAST_WIDTH);
337
338 WinFillRect(hps, &rclDraw, CLR_BLACK);
339
340 ul++;
341 if (ul > LAST_STEPS)
342 ulPhase = 99;
343 }
344
345 ul++;
346
347 DosSleep(WAIT_TIME);
348
349 /* do
350 {
351 DosSleep(0);
352 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
353 &ulTime2,
354 sizeof(ulTime2));
355 } while (ulTime2 < ulFromTime + WAIT_TIME); */
356 } while (ulPhase != 99);
357
358 // sleep a while
359 DosSleep(500);
360 WinFillRect(hps, &rclScreen, CLR_BLACK);
361 DosSleep(500);
362
363 WinShowPointer(HWND_DESKTOP, TRUE);
364}
365
366
367
Note: See TracBrowser for help on using the repository browser.