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

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

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 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_DOSERRORS
44
45#define INCL_WINPOINTERS
46#define INCL_WINSYS
47
48#define INCL_GPILOGCOLORTABLE
49#define INCL_GPIPRIMITIVES
50#define INCL_GPIBITMAPS // added UM 99-10-22; needed for EMX headers
51#include <os2.h>
52
53#include <stdlib.h>
54#include <string.h>
55
56#include "setup.h" // code generation and debugging options
57
58#include "helpers\animate.h"
59
60#include "helpers\datetime.h"
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
89BOOL anmBlowUpBitmap(HPS hps, // in: from WinGetScreenPS(HWND_DESKTOP)
90 HBITMAP hbm, // in: bitmap to be displayed
91 ULONG ulAnimationTime) // in: total animation time (ms)
92{
93 ULONG ulrc = 0;
94 ULONG ulInitialTime,
95 ulNowTime;
96 // ulCurrentSize = 10;
97
98 if (hps)
99 {
100 POINTL ptl = {0, 0};
101 RECTL rtlStretch;
102 ULONG ul,
103 ulSteps = 20;
104 BITMAPINFOHEADER bih;
105 GpiQueryBitmapParameters(hbm, &bih);
106 /* ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)
107 - BMPSPACING
108 - bih.cy; */
109 ptl.x = (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)
110 - bih.cx) / 2;
111 ptl.y = (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)
112 - bih.cy) / 2;
113
114 // we now use ul for the current animation step,
115 // which is a pointer on a scale from 1 to ulAnimationTime;
116 // ul will be recalculated after each animation
117 // step according to how much time the animation
118 // has cost on this display so far. This has the
119 // following advantages:
120 // 1) no matter how fast the system is, the animation
121 // will always last ulAnimationTime milliseconds
122 // 2) since large bitmaps take more time to calculate,
123 // the animation won't appear to slow down then
124 ulInitialTime = dtGetULongTime();
125 ul = 1;
126 ulSteps = 1000;
127 do {
128 LONG cx = (((bih.cx-20) * ul) / ulSteps) + 20;
129 LONG cy = (((bih.cy-20) * ul) / ulSteps) + 20;
130 rtlStretch.xLeft = ptl.x + ((bih.cx - cx) / 2);
131 rtlStretch.yBottom = ptl.y + ((bih.cy - cy) / 2);
132 rtlStretch.xRight = rtlStretch.xLeft + cx;
133 rtlStretch.yTop = rtlStretch.yBottom + cy;
134
135 WinDrawBitmap(hps, hbm, NULL, (PPOINTL)&rtlStretch,
136 0, 0, // we don't need colors
137 DBM_STRETCH);
138
139 ulNowTime = dtGetULongTime();
140
141 // recalculate ul: rule of three based on the
142 // time we've spent on animation so far
143 ul = (ulSteps
144 * (ulNowTime - ulInitialTime)) // time spent so far
145 / ulAnimationTime; // time to spend altogether
146
147 ulrc++; // return count
148
149 } while (ul < ulSteps);
150
151 // finally, draw the 1:1 version
152 WinDrawBitmap(hps, hbm, NULL, &ptl,
153 0, 0, // we don't need colors
154 DBM_NORMAL);
155
156 } // end if (hps)
157
158 return (ulrc);
159}
160
161#define LAST_WIDTH 2
162#define LAST_STEPS 50
163#define WAIT_TIME 10
164
165/* ******************************************************************
166 *
167 * Other animations
168 *
169 ********************************************************************/
170
171/*
172 *@@ anmPowerOff:
173 * displays an animation that looks like a
174 * monitor being turned off; hps must have
175 * been acquired using WinGetScreenPS,
176 * ulSteps should be around 40-50.
177 */
178
179VOID anmPowerOff(HPS hps, ULONG ulSteps)
180{
181 RECTL rclScreen, rclNow, rclLast, rclDraw;
182 ULONG ul = ulSteps;
183 ULONG ulPhase = 1;
184
185 WinQueryWindowRect(HWND_DESKTOP, &rclScreen);
186
187 WinShowPointer(HWND_DESKTOP, FALSE);
188
189 memcpy(&rclLast, &rclScreen, sizeof(RECTL));
190
191 // In order to draw the animation, we tell apart three
192 // "phases", signified by the ulPhase variable. While
193 // ulPhase != 99, we stay in a do-while loop.
194 ul = 0;
195 ulPhase = 1;
196
197 do {
198 ULONG ulFromTime = dtGetULongTime();
199
200 if (ulPhase == 1)
201 {
202 // Phase 1: "shrink" the screen by drawing black
203 // rectangles from the edges towards the center
204 // of the screen. With every loop, we draw the
205 // rectangles a bit closer to the center, until
206 // the center is black too. Sort of like this:
207
208 // ***************************
209 // * black *
210 // * *
211 // * ............. *
212 // * . rclNow: . *
213 // * -> . untouched . <- *
214 // * ............. *
215 // * ^ *
216 // * ! *
217 // ***************************
218
219 // rclNow contains the rectangle _around_ which
220 // the black rectangles are to be drawn. With
221 // every iteration, rclNow is reduced in size.
222 rclNow.xLeft = ((rclScreen.yTop / 2) * ul / ulSteps );
223 rclNow.xRight = (rclScreen.xRight) - rclNow.xLeft;
224 rclNow.yBottom = ((rclScreen.yTop / 2) * ul / ulSteps );
225 rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom;
226
227 if (rclNow.yBottom > (rclNow.yTop - LAST_WIDTH) ) {
228 rclNow.yBottom = (rclScreen.yTop / 2) - LAST_WIDTH;
229 rclNow.yTop = (rclScreen.yTop / 2) + LAST_WIDTH;
230 }
231
232 // draw black rectangle on top of rclNow
233 rclDraw.xLeft = rclLast.xLeft;
234 rclDraw.xRight = rclLast.xRight;
235 rclDraw.yBottom = rclNow.yTop;
236 rclDraw.yTop = rclLast.yTop;
237 WinFillRect(hps, &rclDraw, CLR_BLACK);
238
239 // draw black rectangle left of rclNow
240 rclDraw.xLeft = rclLast.xLeft;
241 rclDraw.xRight = rclNow.xLeft;
242 rclDraw.yBottom = rclLast.yBottom;
243 rclDraw.yTop = rclLast.yTop;
244 WinFillRect(hps, &rclDraw, CLR_BLACK);
245
246 // draw black rectangle right of rclNow
247 rclDraw.xLeft = rclNow.xRight;
248 rclDraw.xRight = rclLast.xRight;
249 rclDraw.yBottom = rclLast.yBottom;
250 rclDraw.yTop = rclLast.yTop;
251 WinFillRect(hps, &rclDraw, CLR_BLACK);
252
253 // draw black rectangle at the bottom of rclNow
254 rclDraw.xLeft = rclLast.xLeft;
255 rclDraw.xRight = rclLast.xRight;
256 rclDraw.yBottom = rclLast.yBottom;
257 rclDraw.yTop = rclNow.yBottom;
258 WinFillRect(hps, &rclDraw, CLR_BLACK);
259
260 // remember rclNow for next iteration
261 memcpy(&rclLast, &rclNow, sizeof(RECTL));
262
263 // done with "shrinking"?
264 if ( rclNow.xRight < ((rclScreen.xRight / 2) + LAST_WIDTH) ) {
265 ulPhase = 2; // exit
266 }
267
268 } else if (ulPhase == 2) {
269 // Phase 2: draw a horizontal white line about
270 // where the last rclNow was. This is only
271 // executed once.
272
273 // ***************************
274 // * black *
275 // * *
276 // * *
277 // * ----------- *
278 // * *
279 // * *
280 // * *
281 // ***************************
282
283 rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
284 rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
285 rclDraw.yBottom = (rclScreen.yTop * 1 / 4);
286 rclDraw.yTop = (rclScreen.yTop * 3 / 4);
287 WinFillRect(hps, &rclDraw, CLR_WHITE);
288
289 ulPhase = 3;
290 ul = 0;
291
292 } else if (ulPhase == 3) {
293 // Phase 3: make the white line shorter with
294 // every iteration by drawing black rectangles
295 // above it. These are drawn closer to the
296 // center with each iteration.
297
298 // ***************************
299 // * black *
300 // * *
301 // * *
302 // * -> ---- <- *
303 // * *
304 // * *
305 // * *
306 // ***************************
307
308 rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
309 rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
310 rclDraw.yTop = (rclScreen.yTop * 3 / 4);
311 rclDraw.yBottom = (rclScreen.yTop * 3 / 4) - ((rclScreen.yTop * 1 / 4) * ul / LAST_STEPS);
312 if (rclDraw.yBottom < ((rclScreen.yTop / 2) + LAST_WIDTH))
313 rclDraw.yBottom = ((rclScreen.yTop / 2) + LAST_WIDTH);
314 WinFillRect(hps, &rclDraw, CLR_BLACK);
315
316 rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
317 rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
318 rclDraw.yBottom = (rclScreen.yTop * 1 / 4);
319 rclDraw.yTop = (rclScreen.yTop * 1 / 4) + ((rclScreen.yTop * 1 / 4) * ul / LAST_STEPS);
320 if (rclDraw.yTop > ((rclScreen.yTop / 2) - LAST_WIDTH))
321 rclDraw.yBottom = ((rclScreen.yTop / 2) - LAST_WIDTH);
322
323 WinFillRect(hps, &rclDraw, CLR_BLACK);
324
325 ul++;
326 if (ul > LAST_STEPS) {
327 ulPhase = 99;
328 }
329 }
330
331 ul++;
332
333 while (dtGetULongTime() < ulFromTime + WAIT_TIME) {
334 // PSZ p = NULL; // keep compiler happy
335 }
336 } while (ulPhase != 99);
337
338 // sleep a while
339 DosSleep(500);
340 WinFillRect(hps, &rclScreen, CLR_BLACK);
341 DosSleep(500);
342
343 WinShowPointer(HWND_DESKTOP, TRUE);
344}
345
346
347
Note: See TracBrowser for help on using the repository browser.