/* * file w32_pixmap.c - double buffer for drawing * * $Id: w32_pixmap.c,v 1.3 2004/06/03 21:10:25 iskywalker Exp $ * * Program XBLAST * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2; or (at your option) * any later version * * This program is distributed in the hope that it will be entertaining, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc. * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "w32_pixmap.h" #include "gui.h" #include "w32_image.h" #include "geom.h" #include "image.h" /* * local constants */ #define CLEAR_WIDTH (24*BASE_X) #define CLEAR_HEIGHT (24*BASE_Y) #define FADE_STEP 16 #define MAX_RECT (MAZE_W*MAZE_H + 4*STAT_W) /* * local types */ typedef struct { RGNDATAHEADER rdh; RECT rect[MAX_RECT]; } RegionData; /* * local variables */ /* pixmap fro double buffering */ static HDC hdcPix = NULL; static HBITMAP clearPix = NULL; /* update rectangles for redraw */ static RegionData rgnData; /* maximum y coordinate */ static int fadeMax; /* step width between lines */ static int fadeStep; /* fade mode*/ static XBFadeMode fadeMode; /* * global function: GUI_ClearPixmap * description: clear pixmap buffer with standard pattern * parameters: none * return value: none */ void GUI_ClearPixmap (void) { HDC hdcSrc; HGDIOBJ oldPix; int x, y; /* get context for destination */ hdcSrc = CreateCompatibleDC (hdcPix); oldPix = SelectObject (hdcPix, pix); (void) SelectObject (hdcSrc, clearPix); /* draw */ for (x = 0; x < PIXW; x += CLEAR_WIDTH) { for (y = 0; y < PIXH + SCOREH; y += CLEAR_HEIGHT) { BitBlt (hdcPix, x, y, 192, 144, hdcSrc, 0, 0, SRCCOPY); } } /* get rid of the device contextes*/ (void) SelectObject (hdcPix, oldPix); DeleteDC (hdcSrc); } /* GUI_ClearPixmap */ /* * library function: ClearRactnagles * description: clear given rectangles in pixmap * parameters: rect - point to array of rectangles * n_rect - number of rectangles in array * return value: none */ void ClearRectangles (HDC hdcDst, HDC hdcSrc, RECT *rect, int nRect) { HGDIOBJ oldSrc; int i; assert (rect != NULL); /* get context for destination */ oldSrc = SelectObject (hdcSrc, clearPix); /* draw */ for (i = 0; i < nRect; i ++) { BitBlt (hdcDst, rect->left, rect->top, BLOCK_WIDTH, BLOCK_HEIGHT, hdcSrc, rect->left % CLEAR_WIDTH, rect->top % CLEAR_HEIGHT, SRCCOPY); rect ++; } /* get rid of the device contextes*/ (void) SelectObject (hdcSrc, oldSrc); } /* ClearRectangles */ /* * redraw window by painting parts of pixmap into it (for WM_PAINT) */ void PaintPixmap (HWND window) { HDC hdc; PAINTSTRUCT ps; HGDIOBJ oldPix; HPALETTE oldPal; unsigned i; HRGN hRgn = CreateRectRgn (0,0,0,0); assert (hRgn != NULL); if (GetUpdateRgn (window, hRgn, FALSE) ) { /* get graphics context for window */ hdc = BeginPaint (window, &ps); /* get region data */ if (0 == GetRegionData (hRgn, sizeof (rgnData), (RGNDATA *) &rgnData) || RDH_RECTANGLES != rgnData.rdh.iType) { /* update full window */ rgnData.rdh.nCount = 1; rgnData.rect->left = 0; rgnData.rect->top = 0; rgnData.rect->right = PIXW; rgnData.rect->bottom = PIXH + SCOREH; } /* draw it */ oldPix = SelectObject (hdcPix, pix); if (NULL != palette) { oldPal = SelectPalette (hdc, palette, FALSE); RealizePalette (hdc); } for (i = 0; i < rgnData.rdh.nCount; i ++) { BitBlt (hdc, rgnData.rect[i].left, rgnData.rect[i].top, rgnData.rect[i].right - rgnData.rect[i].left, rgnData.rect[i].bottom - rgnData.rect[i].top, hdcPix, rgnData.rect[i].left, rgnData.rect[i].top, SRCCOPY); } if (NULL != palette) { (void) SelectPalette (hdc, oldPal, FALSE); } (void) SelectObject (hdcPix, oldPix); /* finish drawing */ EndPaint (window, &ps); } DeleteObject (hRgn); } /* UpdatePixmapRect */ /* * library function: GUI_FlushPixmap * description: copy pixmap to window * parameters: flag - XBTrue only changed parts, XBFalse all of it * return value: none */ void GUI_FlushPixmap (XBBool flag) { if (! flag) { InvalidateRect (window, NULL, FALSE); } UpdateWindow (window); } /* GUI_FlushPixmap */ /* * */ void GUI_FlushScoreBoard (void) { static const RECT rect = { 0, PIXH, PIXW, PIXH + SCOREH }; InvalidateRect (window, &rect, FALSE); UpdateWindow (window); } /* GUI_FlushScoreBoard */ /* * global function: GUI_AddMazeRectangle * description: add a map tile to list of rectangles, which are to be redrawn * parameters: x - column of tile * y - row of tile * return value: none */ void GUI_AddMazeRectangle (int x, int y) { RECT rect; rect.left = BLOCK_WIDTH * x; rect.top = BLOCK_HEIGHT * y; rect.right = BLOCK_WIDTH * (x + 1); rect.bottom = BLOCK_HEIGHT * (y + 1); InvalidateRect (window, &rect, FALSE); } /* GUI_AddMazeRectangle */ /* * global function: GUI_AddStatRectangle * description: add a statusbar tile to list of rectangles, which are to be redrawn * parameters: x - column of tile * y - row of tile * return value: none */ void GUI_AddStatRectangle (int x, int y) { RECT rect; rect.left = STAT_WIDTH * x ; rect.right = STAT_WIDTH * (x + 1); rect.top = MAZE_H * BLOCK_HEIGHT + y * STAT_HEIGHT; if (++y < STAT_H) { rect.bottom = MAZE_H * BLOCK_HEIGHT + y * STAT_HEIGHT; } else { rect.bottom = MAZE_H * BLOCK_HEIGHT + y * STAT_HEIGHT + LED_HEIGHT; } InvalidateRect (window, &rect, FALSE); } /* GUI_AddStatRectangle */ /* * library function: InitPixmap * description: creates bitmap for double buffering * parameters: none * return value: 0 on success, -1 on failure; */ XBBool InitPixmap (void) { HDC hdc; /* get device context of window */ hdc = GetDC (window); if (NULL == hdc) { return XBFalse; } /* create device context for drawing */ hdcPix = CreateCompatibleDC (hdc); if (NULL == hdcPix) { return XBFalse; } /* now create compatible bitmap */ pix = CreateCompatibleBitmap (hdc, PIXW, PIXH+SCOREH); if (NULL == pix) { return XBFalse; } /* Load Bitmap for clearing pixmap */ clearPix = ReadCchPixmap (imgPathMisc, imgFileTitle, COLOR_BLACK, COLOR_GRAY_75, COLOR_MIDNIGHT_BLUE); if (NULL == clearPix) { return XBFalse; } /* give back the window device context */ ReleaseDC (window, hdc); return XBTrue; } /* InitPixmap */ /* * */ void FinishPixmap (void) { if (NULL != hdcPix) { DeleteDC (hdcPix); } if (NULL != clearPix) { DeleteObject (clearPix); } if (NULL != pix) { DeleteObject (pix); } } /* FinishPixmap */ /* * */ void GUI_InitFade (XBFadeMode mode, int maxLines) { assert (maxLines <= PIXH + SCOREH); fadeMax = maxLines; fadeStep = FADE_STEP; fadeMode = mode; } /* GUI_InitFade */ /* * */ XBBool GUI_DoFade (void) { HDC hdc; int y, yStep; if (fadeStep <= 0) { return XBFalse; } /* setup lines to draw */ if (fadeStep == FADE_STEP) { y = 0; yStep = FADE_STEP; } else { y = fadeStep; yStep = 2*fadeStep; } /* prepare drawing */ hdc = GetDC (window); /* draw ... */ if (fadeMode == XBFM_IN) { HGDIOBJ oldPix; oldPix = SelectObject (hdcPix, pix); for (; y < fadeMax; y += yStep) { BitBlt (hdc, 0, y, PIXW, 1, hdcPix, 0, y, SRCCOPY); } SelectObject (hdcPix, oldPix); } else { HGDIOBJ oldPen; HGDIOBJ newPen; if (fadeMode == XBFM_WHITE_OUT) { newPen = GetStockObject (WHITE_PEN); } else { newPen = GetStockObject (BLACK_PEN); } oldPen = SelectObject (hdc, GetStockObject (WHITE_PEN)); for (; y < fadeMax; y += yStep) { MoveToEx (hdc, 0, y, NULL); LineTo (hdc, PIXW-1, y); } SelectObject (hdc, oldPen); DeleteObject (newPen); } ReleaseDC (window, hdc); /* prepare next step */ fadeStep /= 2; /* thatīs all */ return XBTrue; } /* GUI_FadeOut */ /* * end of file w32_pixmap.c */