1 /*
2 * file w32_pixmap.c - double buffer for drawing
3 *
4 * $Id: w32_pixmap.c,v 1.11 2006/02/19 13:33:01 lodott Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 #include "xblast.h"
24 #include "w32_pixmap.h"
25 #include "gui.h"
26
27 #include "w32_image.h"
28
29 #include "geom.h"
30 #include "image.h"
31
32 /*
33 * local constants
34 */
35 #define CLEAR_WIDTH (24*BASE_X)
36 #define CLEAR_HEIGHT (24*BASE_Y)
37 #define FADE_STEP 16
38 /* Changed by VVL (Chat) 12/11/99 */
39 /* Added by Fouf on 01/19/00 15:44:43 */
40 #define MAX_RECT (MAZE_W*(MAZE_H) + STAT_W*4)
41 //#define MAX_RECT (MAZE_W*MAZE_H + 4*STAT_W)
42
43 /*
44 * local types
45 */
46 typedef struct
47 {
48 RGNDATAHEADER rdh;
49 RECT rect[MAX_RECT];
50 } RegionData;
51
52 /*
53 * local variables
54 */
55 /* pixmap fro double buffering */
56 static HDC hdcPix = NULL;
57 static HBITMAP clearPix = NULL;
58 /* update rectangles for redraw */
59 static RegionData rgnData;
60 /* maximum y coordinate */
61 static int fadeMax;
62 /* step width between lines */
63 static int fadeStep;
64 /* fade mode*/
65 static XBFadeMode fadeMode;
66
67 /*
68 * global function: GUI_ClearPixmap
69 * description: clear pixmap buffer with standard pattern
70 * parameters: none
71 * return value: none
72 */
73 void
GUI_ClearPixmap(void)74 GUI_ClearPixmap (void)
75 {
76 HDC hdcSrc;
77 HGDIOBJ oldPix;
78 int x, y;
79
80 /* get context for destination */
81 hdcSrc = CreateCompatibleDC (hdcPix);
82 oldPix = SelectObject (hdcPix, pix);
83 (void)SelectObject (hdcSrc, clearPix);
84 /* draw */
85 for (x = 0; x < PIXW; x += CLEAR_WIDTH) {
86 for (y = 0; y < PIXH + SCOREH; y += CLEAR_HEIGHT) {
87 BitBlt (hdcPix, x, y, 192, 144, hdcSrc, 0, 0, SRCCOPY);
88 }
89 }
90 /* get rid of the device contextes */
91 (void)SelectObject (hdcPix, oldPix);
92 DeleteDC (hdcSrc);
93 } /* GUI_ClearPixmap */
94
95 /*
96 * library function: ClearRactnagles
97 * description: clear given rectangles in pixmap
98 * parameters: rect - point to array of rectangles
99 * n_rect - number of rectangles in array
100 * return value: none
101 */
102 void
ClearRectangles(HDC hdcDst,HDC hdcSrc,RECT * rect,int nRect)103 ClearRectangles (HDC hdcDst, HDC hdcSrc, RECT * rect, int nRect)
104 {
105 HGDIOBJ oldSrc;
106 int i;
107
108 assert (rect != NULL);
109 /* get context for destination */
110 oldSrc = SelectObject (hdcSrc, clearPix);
111 /* draw */
112 for (i = 0; i < nRect; i++) {
113 BitBlt (hdcDst, rect->left, rect->top, BLOCK_WIDTH, BLOCK_HEIGHT,
114 hdcSrc, rect->left % CLEAR_WIDTH, rect->top % CLEAR_HEIGHT, SRCCOPY);
115 rect++;
116 }
117 /* get rid of the device contextes */
118 (void)SelectObject (hdcSrc, oldSrc);
119 } /* ClearRectangles */
120
121 /*
122 * redraw window by painting parts of pixmap into it (for WM_PAINT)
123 */
124 void
PaintPixmap(HWND window)125 PaintPixmap (HWND window)
126 {
127 HDC hdc;
128 PAINTSTRUCT ps;
129 HGDIOBJ oldPix;
130 HPALETTE oldPal = NULL;
131 unsigned i;
132
133 HRGN hRgn = CreateRectRgn (0, 0, 0, 0);
134 assert (hRgn != NULL);
135 if (GetUpdateRgn (window, hRgn, FALSE)) {
136 /* get graphics context for window */
137 hdc = BeginPaint (window, &ps);
138 /* get region data */
139 if (0 == GetRegionData (hRgn, sizeof (rgnData), (RGNDATA *) & rgnData) ||
140 RDH_RECTANGLES != rgnData.rdh.iType) {
141 /* update full window */
142 rgnData.rdh.nCount = 1;
143 rgnData.rect->left = 0;
144 rgnData.rect->top = 0;
145 rgnData.rect->right = PIXW;
146 rgnData.rect->bottom = PIXH + SCOREH;
147 }
148 /* draw it */
149 oldPix = SelectObject (hdcPix, pix);
150 if (NULL != palette) {
151 oldPal = SelectPalette (hdc, palette, FALSE);
152 RealizePalette (hdc);
153 }
154 for (i = 0; i < rgnData.rdh.nCount; i++) {
155 BitBlt (hdc, rgnData.rect[i].left, rgnData.rect[i].top,
156 rgnData.rect[i].right - rgnData.rect[i].left,
157 rgnData.rect[i].bottom - rgnData.rect[i].top, hdcPix, rgnData.rect[i].left,
158 rgnData.rect[i].top, SRCCOPY);
159 }
160 if (NULL != palette) {
161 (void)SelectPalette (hdc, oldPal, FALSE);
162 }
163 (void)SelectObject (hdcPix, oldPix);
164 /* finish drawing */
165 EndPaint (window, &ps);
166 }
167 DeleteObject (hRgn);
168 } /* UpdatePixmapRect */
169
170 /*
171 * library function: GUI_FlushPixmap
172 * description: copy pixmap to window
173 * parameters: flag - XBTrue only changed parts, XBFalse all of it
174 * return value: none
175 */
176 void
GUI_FlushPixmap(XBBool flag)177 GUI_FlushPixmap (XBBool flag)
178 {
179 if (!flag) {
180 InvalidateRect (window, NULL, FALSE);
181 }
182 UpdateWindow (window);
183 } /* GUI_FlushPixmap */
184
185 /*
186 *
187 */
188 void
GUI_FlushScoreBoard(void)189 GUI_FlushScoreBoard (void)
190 {
191 static const RECT rect = {
192 0, PIXH, PIXW, PIXH + SCOREH
193 };
194
195 InvalidateRect (window, &rect, FALSE);
196 UpdateWindow (window);
197 } /* GUI_FlushScoreBoard */
198
199 /*
200 * global function: GUI_AddMazeRectangle
201 * description: add a map tile to list of rectangles, which are to be redrawn
202 * parameters: x - column of tile
203 * y - row of tile
204 * return value: none
205 */
206 void
GUI_AddMazeRectangle(int x,int y)207 GUI_AddMazeRectangle (int x, int y)
208 {
209 RECT rect;
210
211 rect.left = BLOCK_WIDTH * x;
212 rect.top = BLOCK_HEIGHT * y;
213 rect.right = BLOCK_WIDTH * (x + 1);
214 rect.bottom = BLOCK_HEIGHT * (y + 1);
215
216 InvalidateRect (window, &rect, FALSE);
217 } /* GUI_AddMazeRectangle */
218
219 /*
220 * global function: GUI_AddStatRectangle
221 * description: add a statusbar tile to list of rectangles, which are to be redrawn
222 * parameters: x - column of tile
223 * y - row of tile
224 * return value: none
225 */
226 void
GUI_AddStatRectangle(int x,int y)227 GUI_AddStatRectangle (int x, int y)
228 {
229 RECT rect;
230
231 rect.left = STAT_WIDTH * x;
232 rect.right = STAT_WIDTH * (x + 1);
233 rect.top = MAZE_H * BLOCK_HEIGHT + y * STAT_HEIGHT;
234 if (++y < STAT_H) {
235 rect.bottom = MAZE_H * BLOCK_HEIGHT + y * STAT_HEIGHT;
236 }
237 else {
238 rect.bottom = MAZE_H * BLOCK_HEIGHT + y * STAT_HEIGHT + LED_HEIGHT;
239 }
240 //Dbg_Out("add rect %i %i %i %i max %i\n",rect.left ,rect.right ,rect.top ,rect.bottom,MAX_RECT );
241
242 InvalidateRect (window, &rect, FALSE);
243 }
244
245 /* GUI_AddStatRectangle */
246 /* Added by VVL (Chat) 12/11/99 : Begin */
247 void
GUI_AddChatRectangle(int x,int y)248 GUI_AddChatRectangle (int x, int y)
249 {
250 int i = 0, j = 1;
251 RECT rect;
252 rect.left = x * STAT_WIDTH;
253 rect.right = STAT_WIDTH * (x + 1);
254 #ifdef SMPF
255 i = 0;
256 j = 3;
257 #else
258 i = 0;
259 #endif
260 rect.top = (MAZE_H + j) * BLOCK_HEIGHT + i * STAT_HEIGHT + LED_HEIGHT + 8;
261 rect.bottom = (MAZE_H + j) * BLOCK_HEIGHT + (i + 1) * STAT_HEIGHT + LED_HEIGHT + 8;
262 // Dbg_Out("add rect1 %i %i %i %i\n",rect.left ,rect.right ,rect.top ,rect.bottom );
263
264 InvalidateRect (window, &rect, FALSE);
265 }
266
267 /* GUI_AddStatRectangle */
268 /* Added by VVL (Chat) 12/11/99 : Begin */
269 void
GUI_AddTilesRectangle(int x,int y)270 GUI_AddTilesRectangle (int x, int y)
271 {
272 int i = 0, j = 0;
273 RECT rect;
274 rect.left = x * STAT_WIDTH;
275 rect.right = STAT_WIDTH * (x + 1);
276 #ifdef SMPF
277 i = 0;
278 j = 0;
279 #else
280 i = 0;
281 #endif
282 rect.top = (MAZE_H + j) * BLOCK_HEIGHT + i * STAT_HEIGHT + LED_HEIGHT + 8;
283 rect.bottom = (MAZE_H + j) * BLOCK_HEIGHT + (i + 1) * STAT_HEIGHT + LED_HEIGHT + 8;
284 // Dbg_Out("add rect1 %i %i %i %i\n",rect.left ,rect.right ,rect.top ,rect.bottom );
285
286 InvalidateRect (window, &rect, FALSE);
287 }
288
289 /* Added by VVL (Chat) 12/11/99 : End */
290
291 /*
292 * library function: InitPixmap
293 * description: creates bitmap for double buffering
294 * parameters: none
295 * return value: 0 on success, -1 on failure;
296 */
297 XBBool
InitPixmap(void)298 InitPixmap (void)
299 {
300 HDC hdc;
301
302 /* get device context of window */
303 hdc = GetDC (window);
304 if (NULL == hdc) {
305 return XBFalse;
306 }
307 /* create device context for drawing */
308 hdcPix = CreateCompatibleDC (hdc);
309 if (NULL == hdcPix) {
310 return XBFalse;
311 }
312 /* now create compatible bitmap */
313 pix = CreateCompatibleBitmap (hdc, PIXW, PIXH + SCOREH);
314 if (NULL == pix) {
315 return XBFalse;
316 }
317 /* Load Bitmap for clearing pixmap */
318 clearPix =
319 ReadCchPixmap (imgPathMisc, imgFileTitle, COLOR_BLACK, COLOR_GRAY_75, COLOR_MIDNIGHT_BLUE);
320 if (NULL == clearPix) {
321 return XBFalse;
322 }
323 /* give back the window device context */
324 ReleaseDC (window, hdc);
325 return XBTrue;
326 } /* InitPixmap */
327
328 /*
329 *
330 */
331 void
FinishPixmap(void)332 FinishPixmap (void)
333 {
334 if (NULL != hdcPix) {
335 DeleteDC (hdcPix);
336 }
337 if (NULL != clearPix) {
338 DeleteObject (clearPix);
339 }
340 if (NULL != pix) {
341 DeleteObject (pix);
342 }
343 } /* FinishPixmap */
344
345 /*
346 *
347 */
348 void
GUI_InitFade(XBFadeMode mode,int maxLines)349 GUI_InitFade (XBFadeMode mode, int maxLines)
350 {
351 assert (maxLines <= PIXH + SCOREH);
352 fadeMax = maxLines;
353 fadeStep = FADE_STEP;
354 fadeMode = mode;
355 } /* GUI_InitFade */
356
357 /*
358 *
359 */
360 XBBool
GUI_DoFade(void)361 GUI_DoFade (void)
362 {
363 HDC hdc;
364 int y, yStep;
365
366 if (fadeStep <= 0) {
367 return XBFalse;
368 }
369 /* setup lines to draw */
370 if (fadeStep == FADE_STEP) {
371 y = 0;
372 yStep = FADE_STEP;
373 }
374 else {
375 y = fadeStep;
376 yStep = 2 * fadeStep;
377 }
378 /* prepare drawing */
379 hdc = GetDC (window);
380 /* draw ... */
381 if (fadeMode == XBFM_IN) {
382 HGDIOBJ oldPix;
383 oldPix = SelectObject (hdcPix, pix);
384 for (; y < fadeMax; y += yStep) {
385 BitBlt (hdc, 0, y, PIXW, 1, hdcPix, 0, y, SRCCOPY);
386 }
387 SelectObject (hdcPix, oldPix);
388 }
389 else {
390 HGDIOBJ oldPen;
391 HGDIOBJ newPen;
392
393 if (fadeMode == XBFM_WHITE_OUT) {
394 newPen = GetStockObject (WHITE_PEN);
395 }
396 else {
397 newPen = GetStockObject (BLACK_PEN);
398 }
399 oldPen = SelectObject (hdc, GetStockObject (WHITE_PEN));
400 for (; y < fadeMax; y += yStep) {
401 MoveToEx (hdc, 0, y, NULL);
402 LineTo (hdc, PIXW - 1, y);
403 }
404 SelectObject (hdc, oldPen);
405 DeleteObject (newPen);
406 }
407 ReleaseDC (window, hdc);
408 /* prepare next step */
409 fadeStep /= 2;
410 /* that�s all */
411 return XBTrue;
412 } /* GUI_FadeOut */
413
414 /*
415 * end of file w32_pixmap.c
416 */
417