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