win32_gui: implement background glyph rendering

try to use system TrasnparentBlt (or not)
This commit is contained in:
Alex Kompel
2015-06-09 08:34:11 -07:00
parent 2601583121
commit afa0e95e66
7 changed files with 153 additions and 107 deletions

View File

@@ -1,5 +1,5 @@
/* NetHack 3.6 mhmap.c $NHDT-Date: 1432512811 2015/05/25 00:13:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.48 $ */
/* Copyright (C) 2001 by Alex Kompel */
/* Copyright (C) 2001 by Alex Kompel */
/* NetHack may be freely redistributed. See license for details. */
#include "winMS.h"
@@ -16,9 +16,13 @@
extern short glyph2tile[];
#define TILEBMP_X(ntile) ((ntile % GetNHApp()->mapTilesPerLine) * GetNHApp()->mapTile_X)
#define TILEBMP_Y(ntile) ((ntile / GetNHApp()->mapTilesPerLine) * GetNHApp()->mapTile_Y)
/* map window data */
typedef struct mswin_nethack_map_window {
int map[COLNO][ROWNO]; /* glyph map */
int bkmap[COLNO][ROWNO]; /* backround glyph map */
int mapMode; /* current map mode */
boolean bAsciiMode; /* switch ASCII/tiled mode */
@@ -29,7 +33,7 @@ typedef struct mswin_nethack_map_window {
int xScrTile, yScrTile; /* size of display tile */
POINT map_orig; /* map origin point */
HFONT hMapFont; /* font for ASCII mode */
HFONT hMapFont; /* font for ASCII mode */
} NHMapWindow, *PNHMapWindow;
static TCHAR szNHMapWindowClass[] = TEXT("MSNethackMapWndClass");
@@ -449,6 +453,7 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
case MSNH_MSG_PRINT_GLYPH: {
PMSNHMsgPrintGlyph msg_data = (PMSNHMsgPrintGlyph) lParam;
data->map[msg_data->x][msg_data->y] = msg_data->glyph;
data->bkmap[msg_data->x][msg_data->y] = msg_data->bkglyph;
/* invalidate the update area */
nhcoord2display(data, msg_data->x, msg_data->y, &rt);
@@ -589,6 +594,7 @@ onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
for (i = 0; i < COLNO; i++)
for (j = 0; j < ROWNO; j++) {
data->map[i][j] = -1;
data->bkmap[i][j] = -1;
}
data->bAsciiMode = FALSE;
@@ -693,34 +699,53 @@ onPaint(HWND hWnd)
}
SelectObject(hDC, oldFont);
} else {
short ntile;
int t_x, t_y;
int glyph, bkglyph;
RECT glyph_rect;
/* prepare tiles DC for mapping */
tileDC = CreateCompatibleDC(hDC);
saveBmp = SelectObject(tileDC, GetNHApp()->bmpMapTiles);
/* draw the map */
for (i = paint_rt.left; i < paint_rt.right; i++)
for (j = paint_rt.top; j < paint_rt.bottom; j++)
if (data->map[i][j] >= 0) {
short ntile;
int t_x, t_y;
RECT glyph_rect;
for (j = paint_rt.top; j < paint_rt.bottom; j++) {
glyph = data->map[i][j];
bkglyph = (glyph >= 0)? data->bkmap[i][j] : -1;
ntile = glyph2tile[data->map[i][j]];
t_x = (ntile % GetNHApp()->mapTilesPerLine)
* GetNHApp()->mapTile_X;
t_y = (ntile / GetNHApp()->mapTilesPerLine)
* GetNHApp()->mapTile_Y;
if (glyph == bkglyph) {
glyph = -1;
}
if (bkglyph >= 0) {
ntile = glyph2tile[bkglyph];
t_x = TILEBMP_X(ntile);
t_y = TILEBMP_Y(ntile);
nhcoord2display(data, i, j, &glyph_rect);
StretchBlt(hDC, glyph_rect.left, glyph_rect.top,
data->xScrTile, data->yScrTile, tileDC,
t_x, t_y, GetNHApp()->mapTile_X,
GetNHApp()->mapTile_Y, SRCCOPY);
if (glyph_is_pet(data->map[i][j])
}
if (glyph >= 0) {
ntile = glyph2tile[glyph];
t_x = TILEBMP_X(ntile);
t_y = TILEBMP_Y(ntile);
nhcoord2display(data, i, j, &glyph_rect);
(*GetNHApp()->lpfnTransparentBlt)(
hDC, glyph_rect.left, glyph_rect.top,
data->xScrTile, data->yScrTile, tileDC,
t_x, t_y, GetNHApp()->mapTile_X,
GetNHApp()->mapTile_Y, TILE_BK_COLOR);
if (glyph_is_pet(glyph)
&& iflags.wc_hilite_pet) {
/* apply pet mark transparently over
pet image */
pet image */
HDC hdcPetMark;
HBITMAP bmPetMarkOld;
@@ -729,7 +754,7 @@ onPaint(HWND hWnd)
bmPetMarkOld = SelectObject(
hdcPetMark, GetNHApp()->bmpPetMark);
nhapply_image_transparent(
(*GetNHApp()->lpfnTransparentBlt)(
hDC, glyph_rect.left, glyph_rect.top,
data->xScrTile, data->yScrTile, hdcPetMark, 0,
0, TILE_X, TILE_Y, TILE_BK_COLOR);
@@ -737,6 +762,7 @@ onPaint(HWND hWnd)
DeleteDC(hdcPetMark);
}
}
}
SelectObject(tileDC, saveBmp);
DeleteDC(tileDC);
}
@@ -987,87 +1013,3 @@ nhcolor_to_RGB(int c)
}
}
/* apply bitmap pointed by sourceDc transparently over
bitmap pointed by hDC */
typedef BOOL(WINAPI *LPTRANSPARENTBLT)(HDC, int, int, int, int, HDC, int, int,
int, int, UINT);
void
nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
HDC sourceDC, int s_x, int s_y, int s_width,
int s_height, COLORREF cTransparent)
{
/* Don't use TransparentBlt; According to Microsoft, it contains a memory
* leak in Window 95/98. */
HDC hdcMem, hdcBack, hdcObject, hdcSave;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
/* Create some DCs to hold temporary data. */
hdcBack = CreateCompatibleDC(hDC);
hdcObject = CreateCompatibleDC(hDC);
hdcMem = CreateCompatibleDC(hDC);
hdcSave = CreateCompatibleDC(hDC);
/* this is bitmap for our pet image */
bmSave = CreateCompatibleBitmap(hDC, width, height);
/* Monochrome DC */
bmAndBack = CreateBitmap(width, height, 1, 1, NULL);
bmAndObject = CreateBitmap(width, height, 1, 1, NULL);
/* resulting bitmap */
bmAndMem = CreateCompatibleBitmap(hDC, width, height);
/* Each DC must select a bitmap object to store pixel data. */
bmBackOld = SelectObject(hdcBack, bmAndBack);
bmObjectOld = SelectObject(hdcObject, bmAndObject);
bmMemOld = SelectObject(hdcMem, bmAndMem);
bmSaveOld = SelectObject(hdcSave, bmSave);
/* copy source image because it is going to be overwritten */
StretchBlt(hdcSave, 0, 0, width, height, sourceDC, s_x, s_y, s_width,
s_height, SRCCOPY);
/* Set the background color of the source DC to the color.
contained in the parts of the bitmap that should be transparent */
cColor = SetBkColor(hdcSave, cTransparent);
/* Create the object mask for the bitmap by performing a BitBlt
from the source bitmap to a monochrome bitmap. */
BitBlt(hdcObject, 0, 0, width, height, hdcSave, 0, 0, SRCCOPY);
/* Set the background color of the source DC back to the original
color. */
SetBkColor(hdcSave, cColor);
/* Create the inverse of the object mask. */
BitBlt(hdcBack, 0, 0, width, height, hdcObject, 0, 0, NOTSRCCOPY);
/* Copy background to the resulting image */
BitBlt(hdcMem, 0, 0, width, height, hDC, x, y, SRCCOPY);
/* Mask out the places where the source image will be placed. */
BitBlt(hdcMem, 0, 0, width, height, hdcObject, 0, 0, SRCAND);
/* Mask out the transparent colored pixels on the source image. */
BitBlt(hdcSave, 0, 0, width, height, hdcBack, 0, 0, SRCAND);
/* XOR the source image with the beckground. */
BitBlt(hdcMem, 0, 0, width, height, hdcSave, 0, 0, SRCPAINT);
/* blt resulting image to the screen */
BitBlt(hDC, x, y, width, height, hdcMem, 0, 0, SRCCOPY);
/* cleanup */
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
}

View File

@@ -1056,7 +1056,7 @@ onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
if (GetNHApp()->bmpMapTiles == GetNHApp()->bmpTiles) {
/* using original nethack tiles - apply image transparently */
nhapply_image_transparent(lpdis->hDC, x, y, TILE_X, TILE_Y,
(*GetNHApp()->lpfnTransparentBlt)(lpdis->hDC, x, y, TILE_X, TILE_Y,
tileDC, t_x, t_y, TILE_X, TILE_Y,
TILE_BK_COLOR);
} else {

View File

@@ -36,6 +36,7 @@ typedef struct mswin_nhmsg_print_glyph {
XCHAR_P x;
XCHAR_P y;
int glyph;
int bkglyph;
} MSNHMsgPrintGlyph, *PMSNHMsgPrintGlyph;
typedef struct mswin_nhmsg_cliparound {

View File

@@ -206,7 +206,7 @@ NHSplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
hdcBitmap = CreateCompatibleDC(hdc);
SetBkMode(hdc, OPAQUE);
OldBitmap = SelectObject(hdcBitmap, GetNHApp()->bmpSplash);
nhapply_image_transparent(hdc, SPLASH_OFFSET_X, SPLASH_OFFSET_Y,
(*GetNHApp()->lpfnTransparentBlt)(hdc, SPLASH_OFFSET_X, SPLASH_OFFSET_Y,
SPLASH_WIDTH, SPLASH_HEIGHT, hdcBitmap, 0,
0, SPLASH_WIDTH, SPLASH_HEIGHT,
TILE_BK_COLOR);

View File

@@ -1280,6 +1280,7 @@ mswin_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph, int bkglyph)
data.x = x;
data.y = y;
data.glyph = glyph;
data.bkglyph = bkglyph;
SendMessage(GetNHApp()->windowlist[wid].win, WM_MSNH_COMMAND,
(WPARAM) MSNH_MSG_PRINT_GLYPH, (LPARAM) &data);
}

View File

@@ -1,5 +1,5 @@
/* NetHack 3.6 winMS.h $NHDT-Date: 1433806621 2015/06/08 23:37:01 $ $NHDT-Branch: master $:$NHDT-Revision: 1.37 $ */
/* Copyright (C) 2001 by Alex Kompel */
/* Copyright (C) 2001 by Alex Kompel */
/* NetHack may be freely redistributed. See license for details. */
#ifndef WINMS_H
@@ -58,6 +58,9 @@ typedef struct mswin_nhwindow_data {
int dead;
} MSNHWinData, *PMSNHWinData;
typedef BOOL(WINAPI *LPTRANSPARENTBLT)(HDC, int, int, int, int, HDC, int, int,
int, int, UINT);
typedef struct mswin_nhwindow_app {
HINSTANCE hApp;
HWND hMainWnd;
@@ -107,6 +110,8 @@ typedef struct mswin_nhwindow_app {
BOOL bWindowsLocked; /* TRUE if windows are "locked" - no captions */
BOOL bNoSounds; /* disable sounds */
LPTRANSPARENTBLT lpfnTransparentBlt; /* transparent blt function */
} NHWinApp, *PNHWinApp;
#define E extern
@@ -182,9 +187,6 @@ winid mswin_winid_from_type(int type);
winid mswin_winid_from_handle(HWND hWnd);
void mswin_window_mark_dead(winid wid);
void bail(const char *mesg);
void nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
HDC sourceDC, int s_x, int s_y, int s_width,
int s_height, COLORREF cTransparent);
void mswin_popup_display(HWND popup, int *done_indicator);
void mswin_popup_destroy(HWND popup);

View File

@@ -1,5 +1,5 @@
/* NetHack 3.6 winhack.c $NHDT-Date: 1432512811 2015/05/25 00:13:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.40 $ */
/* Copyright (C) 2001 by Alex Kompel */
/* NetHack 3.6 winhack.c $NHDT-Date: 1432512811 2015/05/25 00:13:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.40 $ */
/* Copyright (C) 2001 by Alex Kompel */
/* NetHack may be freely redistributed. See license for details. */
// winhack.cpp : Defines the entry point for the application.
@@ -50,6 +50,10 @@ Version _WIN_32IE Platform/IE
extern void FDECL(nethack_exit, (int));
static TCHAR *_get_cmd_arg(TCHAR *pCmdLine);
static HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor);
BOOL WINAPI
_nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
HDC sourceDC, int s_x, int s_y, int s_width,
int s_height, UINT cTransparent);
// Global Variables:
NHWinApp _nethack_app;
@@ -78,6 +82,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
char buf[BUFSZ];
DWORD major, minor;
boolean resuming;
/* OSVERSIONINFO osvi; */
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
@@ -121,6 +126,17 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
_nethack_app.bNoSounds = FALSE;
#if 0 /* GdiTransparentBlt does not render spash bitmap for whatever reason */
/* use system-provided TransparentBlt for Win2k+ */
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion >= 5)
_nethack_app.lpfnTransparentBlt = GdiTransparentBlt;
else
#endif
_nethack_app.lpfnTransparentBlt = _nhapply_image_transparent;
// init controls
if (FAILED(GetComCtlVersion(&major, &minor))) {
char buf[TBUFSZ];
@@ -287,3 +303,87 @@ GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
FreeLibrary(hComCtl);
return hr;
}
/* apply bitmap pointed by sourceDc transparently over
bitmap pointed by hDC */
BOOL WINAPI
_nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
HDC sourceDC, int s_x, int s_y, int s_width,
int s_height, UINT cTransparent)
{
/* Don't use TransparentBlt; According to Microsoft, it contains a memory
* leak in Window 95/98. */
HDC hdcMem, hdcBack, hdcObject, hdcSave;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
/* Create some DCs to hold temporary data. */
hdcBack = CreateCompatibleDC(hDC);
hdcObject = CreateCompatibleDC(hDC);
hdcMem = CreateCompatibleDC(hDC);
hdcSave = CreateCompatibleDC(hDC);
/* this is bitmap for our pet image */
bmSave = CreateCompatibleBitmap(hDC, width, height);
/* Monochrome DC */
bmAndBack = CreateBitmap(width, height, 1, 1, NULL);
bmAndObject = CreateBitmap(width, height, 1, 1, NULL);
/* resulting bitmap */
bmAndMem = CreateCompatibleBitmap(hDC, width, height);
/* Each DC must select a bitmap object to store pixel data. */
bmBackOld = SelectObject(hdcBack, bmAndBack);
bmObjectOld = SelectObject(hdcObject, bmAndObject);
bmMemOld = SelectObject(hdcMem, bmAndMem);
bmSaveOld = SelectObject(hdcSave, bmSave);
/* copy source image because it is going to be overwritten */
StretchBlt(hdcSave, 0, 0, width, height, sourceDC, s_x, s_y, s_width,
s_height, SRCCOPY);
/* Set the background color of the source DC to the color.
contained in the parts of the bitmap that should be transparent */
cColor = SetBkColor(hdcSave, cTransparent);
/* Create the object mask for the bitmap by performing a BitBlt
from the source bitmap to a monochrome bitmap. */
BitBlt(hdcObject, 0, 0, width, height, hdcSave, 0, 0, SRCCOPY);
/* Set the background color of the source DC back to the original
color. */
SetBkColor(hdcSave, cColor);
/* Create the inverse of the object mask. */
BitBlt(hdcBack, 0, 0, width, height, hdcObject, 0, 0, NOTSRCCOPY);
/* Copy background to the resulting image */
BitBlt(hdcMem, 0, 0, width, height, hDC, x, y, SRCCOPY);
/* Mask out the places where the source image will be placed. */
BitBlt(hdcMem, 0, 0, width, height, hdcObject, 0, 0, SRCAND);
/* Mask out the transparent colored pixels on the source image. */
BitBlt(hdcSave, 0, 0, width, height, hdcBack, 0, 0, SRCAND);
/* XOR the source image with the beckground. */
BitBlt(hdcMem, 0, 0, width, height, hdcSave, 0, 0, SRCPAINT);
/* blt resulting image to the screen */
BitBlt(hDC, x, y, width, height, hdcMem, 0, 0, SRCCOPY);
/* cleanup */
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
return TRUE;
}