From 52cbbdafae462e7416e52920bdb58722ce4799d8 Mon Sep 17 00:00:00 2001 From: Bart House Date: Fri, 16 Nov 2018 12:39:04 -0800 Subject: [PATCH] Completed map back buffer work and implemented map cursor blink. Map back buffer work is done eliminating all flickering caused by clears of the front buffer during partial updates. Implemented a cursor blink in both ascii and tile modes. Fixed bug where we would lose fit to screen when entering rogue level. --- win/win32/mhmap.c | 667 +++++++++++++++++++++++--------------------- win/win32/mhmap.h | 1 + win/win32/mswproc.c | 10 +- 3 files changed, 361 insertions(+), 317 deletions(-) diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index 3001afdd8..d035c7266 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -18,6 +18,9 @@ #define NHMAP_FONT_NAME TEXT("Terminal") #define MAXWINDOWTEXT 255 +#define CURSOR_BLINK_INTERVAL 1000 // milliseconds +#define CURSOR_HEIGHT 2 // pixels + extern short glyph2tile[]; #define TILEBMP_X(ntile) \ @@ -27,8 +30,11 @@ extern short glyph2tile[]; /* map window data */ typedef struct mswin_nethack_map_window { - int map[COLNO][ROWNO]; /* glyph map */ - int bkmap[COLNO][ROWNO]; /* backround glyph map */ + HWND hWnd; /* window */ + + int map[COLNO][ROWNO]; /* glyph map */ + int bkmap[COLNO][ROWNO]; /* backround glyph map */ + boolean mapDirty[COLNO][ROWNO]; /* dirty flag for map */ int mapMode; /* current map mode */ boolean bAsciiMode; /* switch ASCII/tiled mode */ @@ -49,6 +55,16 @@ typedef struct mswin_nethack_map_window { double backScale; /* scaling from source to back buffer */ double frontScale; /* scaling from back to front */ double monitorScale; /* from 96dpi to monitor dpi*/ + + boolean cursorOn; + int yFrontCursor; /* height of cursor inback buffer in pixels */ + + int backWidth; /* back buffer width */ + int backHeight; /* back buffer height */ + HBITMAP hBackBuffer; /* back buffe bitmap */ + HDC backBufferDC; /* back buffer drawing context */ + + HDC tileDC; /* tile drawing context */ } NHMapWindow, *PNHMapWindow; @@ -61,6 +77,12 @@ static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam); static void onPaint(HWND hWnd); static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam); static void nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut); +static void paint(PNHMapWindow data, int i, int j); +static void dirtyAll(PNHMapWindow data); +static void dirty(PNHMapWindow data, int i, int j); +static void setGlyph(PNHMapWindow data, int i, int j, int fg, int bg); +static void clearAll(PNHMapWindow data); + #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2) static void nhglyph2charcolor(short glyph, uchar *ch, int *color); #endif @@ -69,7 +91,7 @@ HWND mswin_init_map_window() { static int run_once = 0; - HWND ret; + HWND hWnd; RECT rt; if (!run_once) { @@ -85,7 +107,7 @@ mswin_init_map_window() } /* create map window object */ - ret = CreateWindow( + hWnd = CreateWindow( szNHMapWindowClass, /* registered class name */ NULL, /* window name */ WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_CLIPSIBLINGS @@ -98,16 +120,19 @@ mswin_init_map_window() NULL, /* menu handle or child identifier */ GetNHApp()->hApp, /* handle to application instance */ NULL); /* window-creation data */ - if (!ret) { + if (!hWnd) { panic("Cannot create map window"); } /* Set window caption */ - SetWindowText(ret, "Map"); + SetWindowText(hWnd, "Map"); - mswin_apply_window_style(ret); + mswin_apply_window_style(hWnd); - return ret; + /* set cursor blink timer */ + SetTimer(hWnd, 0, CURSOR_BLINK_INTERVAL, NULL); + + return hWnd; } void @@ -131,7 +156,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) // calculate back buffer scale data->monitorScale = win10_monitor_scale(hWnd); - if (data->bAsciiMode) { + if (data->bAsciiMode || Is_rogue_level(&u.uz)) { data->backScale = data->monitorScale; } else { data->backScale = 1.0; @@ -141,12 +166,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) data->xBackTile = (int) (data->tileWidth * data->backScale); data->yBackTile = (int) (data->tileHeight * data->backScale); - if (data->bAsciiMode) { - - /* create font */ - if (data->hMapFont) - DeleteObject(data->hMapFont); - + if (data->bAsciiMode || Is_rogue_level(&u.uz)) { LOGFONT lgfnt; ZeroMemory(&lgfnt, sizeof(lgfnt)); @@ -171,17 +191,14 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) } TEXTMETRIC textMetrics; + HFONT font; while (1) { - data->hMapFont = CreateFontIndirect(&lgfnt); + font = CreateFontIndirect(&lgfnt); - HDC hdc = GetDC(NULL); - HFONT savedFont = SelectObject(hdc, data->hMapFont); + SelectObject(data->backBufferDC, font); - GetTextMetrics(hdc, &textMetrics); - - SelectObject(hdc, savedFont); - ReleaseDC(NULL, hdc); + GetTextMetrics(data->backBufferDC, &textMetrics); if (textMetrics.tmHeight > data->yBackTile) { lgfnt.lfHeight++; @@ -196,6 +213,11 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) break; } + if (data->hMapFont) + DeleteObject(data->hMapFont); + + data->hMapFont = font; + data->bUnicodeFont = winos_font_support_cp437(data->hMapFont); // set tile size to match font metrics @@ -205,24 +227,46 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) } + int backWidth = COLNO * data->xBackTile; + int backHeight = ROWNO * data->yBackTile; + + /* create back buffer */ + + if (data->backWidth != backWidth || data->backHeight != backHeight) { + + HDC frontBufferDC = GetDC(hWnd); + HBITMAP hBackBuffer = CreateCompatibleBitmap(frontBufferDC, backWidth, backHeight); + ReleaseDC(hWnd, frontBufferDC); + + if (data->hBackBuffer != NULL) { + SelectBitmap(data->backBufferDC, hBackBuffer); + DeleteObject(data->hBackBuffer); + } + + data->backWidth = backWidth; + data->backHeight = backHeight; + + SelectBitmap(data->backBufferDC, hBackBuffer); + data->hBackBuffer = hBackBuffer; + } + /* calculate front buffer tile size */ if (wnd_size.cx > 0 && wnd_size.cy > 0 && data->bFitToScreenMode) { double windowAspectRatio = (double) wnd_size.cx / (double) wnd_size.cy; - UINT backWidth = COLNO * data->xBackTile; - UINT backHeight = ROWNO * data->yBackTile; - double backAspectRatio = (double) backWidth / (double) backHeight; + double backAspectRatio = + (double) data->backWidth / (double) data->backHeight; if (windowAspectRatio > backAspectRatio) - data->frontScale = (double) wnd_size.cy / (double) backHeight; + data->frontScale = (double) wnd_size.cy / (double) data->backHeight; else - data->frontScale = (double) wnd_size.cx / (double) backWidth; + data->frontScale = (double) wnd_size.cx / (double) data->backWidth; } else { - if (data->bAsciiMode) { + if (data->bAsciiMode || Is_rogue_level(&u.uz)) { data->frontScale = 1.0; } else { data->frontScale = data->monitorScale; @@ -233,6 +277,9 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) data->xFrontTile = (int) ((double) data->xBackTile * data->frontScale); data->yFrontTile = (int) ((double) data->yBackTile * data->frontScale); + /* calcuate ASCII cursor height */ + data->yFrontCursor = (int) ((double) CURSOR_HEIGHT * data->backScale); + /* set map origin point */ data->map_orig.x = max(0, client_rt.left + (wnd_size.cx - data->xFrontTile * COLNO) / 2); @@ -280,8 +327,10 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) mswin_cliparound(data->xCur, data->yCur); - if (redraw) + if (redraw) { + dirtyAll(data); InvalidateRect(hWnd, NULL, TRUE); + } } /* set map mode */ @@ -513,6 +562,12 @@ MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0); break; + case WM_TIMER: + data->cursorOn = !data->cursorOn; + dirty(data, data->xCur, data->yCur); + break; + + default: return DefWindowProc(hWnd, message, wParam, lParam); } @@ -524,25 +579,13 @@ void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { PNHMapWindow data; - RECT rt; data = (PNHMapWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); switch (wParam) { case MSNH_MSG_PRINT_GLYPH: { PMSNHMsgPrintGlyph msg_data = (PMSNHMsgPrintGlyph) lParam; - if ((data->map[msg_data->x][msg_data->y] != msg_data->glyph) - || (data->bkmap[msg_data->x][msg_data->y] != msg_data->bkglyph)) { - 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. Erase backround if there - is nothing to paint or we are in text mode */ - nhcoord2display(data, msg_data->x, msg_data->y, &rt); - InvalidateRect(hWnd, &rt, - (((msg_data->glyph == NO_GLYPH) - && (msg_data->bkglyph == NO_GLYPH)) - || data->bAsciiMode || Is_rogue_level(&u.uz))); - } + setGlyph(data, msg_data->x, msg_data->y, + msg_data->glyph, msg_data->bkglyph); } break; case MSNH_MSG_CLIPAROUND: { @@ -589,44 +632,22 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) } } break; - case MSNH_MSG_CLEAR_WINDOW: { - int i, j; - for (i = 0; i < COLNO; i++) - for (j = 0; j < ROWNO; j++) { - data->map[i][j] = NO_GLYPH; - data->bkmap[i][j] = NO_GLYPH; - } - InvalidateRect(hWnd, NULL, TRUE); - } break; + case MSNH_MSG_CLEAR_WINDOW: + clearAll(data); + break; case MSNH_MSG_CURSOR: { PMSNHMsgCursor msg_data = (PMSNHMsgCursor) lParam; - HDC hdc; - RECT rt; - /* move focus rectangle at the cursor postion */ - hdc = GetDC(hWnd); + if (data->xCur != msg_data->x || data->yCur != msg_data->y) { - nhcoord2display(data, data->xCur, data->yCur, &rt); - if (data->bAsciiMode) { - PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, - rt.bottom - rt.top, DSTINVERT); - } else { - DrawFocusRect(hdc, &rt); + dirty(data, data->xCur, data->yCur); + dirty(data, msg_data->x, msg_data->y); + + data->xCur = msg_data->x; + data->yCur = msg_data->y; } - - data->xCur = msg_data->x; - data->yCur = msg_data->y; - - nhcoord2display(data, data->xCur, data->yCur, &rt); - if (data->bAsciiMode) { - PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, - rt.bottom - rt.top, DSTINVERT); - } else { - DrawFocusRect(hdc, &rt); - } - - ReleaseDC(hWnd, hdc); + } break; case MSNH_MSG_GETTEXT: { @@ -666,7 +687,6 @@ void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) { PNHMapWindow data; - int i, j; UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); @@ -677,11 +697,8 @@ onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) panic("out of memory"); ZeroMemory(data, sizeof(NHMapWindow)); - for (i = 0; i < COLNO; i++) - for (j = 0; j < ROWNO; j++) { - data->map[i][j] = NO_GLYPH; - data->bkmap[i][j] = NO_GLYPH; - } + + data->hWnd = hWnd; data->bAsciiMode = FALSE; @@ -690,256 +707,276 @@ onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) data->tileWidth = GetNHApp()->mapTile_X; data->tileHeight = GetNHApp()->mapTile_Y; + HDC hDC = GetDC(hWnd); + data->backBufferDC = CreateCompatibleDC(hDC); + data->tileDC = CreateCompatibleDC(hDC); + ReleaseDC(hWnd, hDC); + + SelectObject(data->tileDC, GetNHApp()->bmpMapTiles); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data); + + clearAll(data); + } +static void +paintTile(PNHMapWindow data, int i, int j, RECT * rect) +{ + short ntile; + int t_x, t_y; + int glyph, bkglyph; + int layer; +#ifdef USE_PILEMARK + int color; + unsigned special; + int mgch; +#endif + layer = 0; + glyph = data->map[i][j]; + bkglyph = data->bkmap[i][j]; + + if (bkglyph != NO_GLYPH) { + ntile = glyph2tile[bkglyph]; + t_x = TILEBMP_X(ntile); + t_y = TILEBMP_Y(ntile); + + StretchBlt(data->backBufferDC, rect->left, rect->top, + data->xBackTile, data->yBackTile, data->tileDC, + t_x, t_y, GetNHApp()->mapTile_X, + GetNHApp()->mapTile_Y, SRCCOPY); + layer++; + } + + if ((glyph != NO_GLYPH) && (glyph != bkglyph)) { + ntile = glyph2tile[glyph]; + t_x = TILEBMP_X(ntile); + t_y = TILEBMP_Y(ntile); + + if (layer > 0) { + (*GetNHApp()->lpfnTransparentBlt)( + data->backBufferDC, rect->left, rect->top, + data->xBackTile, data->yBackTile, data->tileDC, t_x, + t_y, GetNHApp()->mapTile_X, + GetNHApp()->mapTile_Y, TILE_BK_COLOR); + } else { + StretchBlt(data->backBufferDC, rect->left, rect->top, + data->xBackTile, data->yBackTile, data->tileDC, + t_x, t_y, GetNHApp()->mapTile_X, + GetNHApp()->mapTile_Y, SRCCOPY); + } + + layer++; + } + +#ifdef USE_PILEMARK + /* rely on NetHack core helper routine */ + (void) mapglyph(data->map[i][j], &mgch, &color, &special, + i, j); + if ((glyph != NO_GLYPH) && (special & MG_PET) +#else + if ((glyph != NO_GLYPH) && glyph_is_pet(glyph) +#endif + && iflags.wc_hilite_pet) { + /* apply pet mark transparently over + pet image */ + HDC hdcPetMark; + HBITMAP bmPetMarkOld; + + /* this is DC for petmark bitmap */ + hdcPetMark = CreateCompatibleDC(data->backBufferDC); + bmPetMarkOld = + SelectObject(hdcPetMark, GetNHApp()->bmpPetMark); + + (*GetNHApp()->lpfnTransparentBlt)( + data->backBufferDC, rect->left, rect->top, + data->xBackTile, data->yBackTile, hdcPetMark, 0, 0, + TILE_X, TILE_Y, TILE_BK_COLOR); + SelectObject(hdcPetMark, bmPetMarkOld); + DeleteDC(hdcPetMark); + } +#ifdef USE_PILEMARK + if ((glyph != NO_GLYPH) && (special & MG_OBJPILE) + && iflags.hilite_pile) { + /* apply pilemark transparently over other image */ + HDC hdcPileMark; + HBITMAP bmPileMarkOld; + + /* this is DC for pilemark bitmap */ + hdcPileMark = CreateCompatibleDC(data->backBufferDC); + bmPileMarkOld = SelectObject(hdcPileMark, + GetNHApp()->bmpPileMark); + + (*GetNHApp()->lpfnTransparentBlt)( + data->backBufferDC, rect->left, rect->top, + data->xBackTile, data->yBackTile, hdcPileMark, 0, 0, + TILE_X, TILE_Y, TILE_BK_COLOR); + SelectObject(hdcPileMark, bmPileMarkOld); + DeleteDC(hdcPileMark); + } +#endif + + if (i == data->xCur && j == data->yCur && data->cursorOn) + DrawFocusRect(data->backBufferDC, rect); +} + + +static void +paintGlyph(PNHMapWindow data, int i, int j, RECT * rect) +{ + if (data->map[i][j] >= 0) { + + char ch; + WCHAR wch; + int color; + unsigned special; + int mgch; + HBRUSH back_brush; + COLORREF OldFg; + + SetBkMode(data->backBufferDC, TRANSPARENT); + + HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0)); + FillRect(data->backBufferDC, rect, blackBrush); + DeleteObject(blackBrush); + + #if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2) + nhglyph2charcolor(data->map[i][j], &ch, &color); + OldFg = SetTextColor(hDC, nhcolor_to_RGB(color)); + #else + /* rely on NetHack core helper routine */ + (void) mapglyph(data->map[i][j], &mgch, &color, + &special, i, j); + ch = (char) mgch; + if (((special & MG_PET) && iflags.hilite_pet) + || ((special & (MG_DETECT | MG_BW_LAVA)) + && iflags.use_inverse)) { + back_brush = + CreateSolidBrush(nhcolor_to_RGB(CLR_GRAY)); + FillRect(data->backBufferDC, rect, back_brush); + DeleteObject(back_brush); + switch (color) { + case CLR_GRAY: + case CLR_WHITE: + OldFg = SetTextColor( + data->backBufferDC, nhcolor_to_RGB(CLR_BLACK)); + break; + default: + OldFg = + SetTextColor(data->backBufferDC, nhcolor_to_RGB(color)); + } + } else { + OldFg = SetTextColor(data->backBufferDC, nhcolor_to_RGB(color)); + } + #endif + if (data->bUnicodeFont) { + wch = winos_ascii_to_wide(ch); + DrawTextW(data->backBufferDC, &wch, 1, rect, + DT_CENTER | DT_VCENTER | DT_NOPREFIX + | DT_SINGLELINE); + } else { + DrawTextA(data->backBufferDC, &ch, 1, rect, + DT_CENTER | DT_VCENTER | DT_NOPREFIX + | DT_SINGLELINE); + } + + SetTextColor(data->backBufferDC, OldFg); + } + + if (i == data->xCur && j == data->yCur && data->cursorOn) + PatBlt(data->backBufferDC, + rect->left, rect->bottom - data->yFrontCursor, + rect->right - rect->left, + data->yFrontCursor, + DSTINVERT); +} + +static void setGlyph(PNHMapWindow data, int i, int j, int fg, int bg) +{ + if ((data->map[i][j] != fg) || (data->bkmap[i][j] != bg)) { + data->map[i][j] = fg; + data->bkmap[i][j] = bg; + data->mapDirty[i][j] = TRUE; + + RECT rect; + nhcoord2display(data, i, j, &rect); + InvalidateRect(data->hWnd, &rect, FALSE); + } +} + +static void clearAll(PNHMapWindow data) +{ + for (int x = 0; x < COLNO; x++) + for (int y = 0; y < ROWNO; y++) { + data->map[x][y] = NO_GLYPH; + data->bkmap[x][y] = NO_GLYPH; + data->mapDirty[x][y] = TRUE; + } + InvalidateRect(data->hWnd, NULL, FALSE); +} + +static void dirtyAll(PNHMapWindow data) +{ + for (int i = 0; i < COLNO; i++) + for (int j = 0; j < ROWNO; j++) + data->mapDirty[i][j] = TRUE; + + InvalidateRect(data->hWnd, NULL, FALSE); +} + +static void dirty(PNHMapWindow data, int x, int y) +{ + data->mapDirty[x][y] = TRUE; + + RECT rt; + nhcoord2display(data, data->xCur, data->yCur, &rt); + + InvalidateRect(data->hWnd, &rt, FALSE); +} + +static void +paint(PNHMapWindow data, int i, int j) +{ + RECT rect; + + rect.left = i * data->xBackTile; + rect.top = j * data->yBackTile; + rect.right = rect.left + data->xBackTile; + rect.bottom = rect.top + data->yBackTile; + + if (data->bAsciiMode || Is_rogue_level(&u.uz)) { + paintGlyph(data, i, j, &rect); + } else { + paintTile(data, i, j, &rect); + } + + data->mapDirty[i][j] = FALSE; +} + + /* on WM_PAINT */ void onPaint(HWND hWnd) { - PNHMapWindow data; + PNHMapWindow data = (PNHMapWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); + + /* update back buffer */ + for (int i = 0; i < COLNO; i++) + for (int j = 0; j < ROWNO; j++) + if (data->mapDirty[i][j]) + paint(data, i, j); + PAINTSTRUCT ps; - HDC tileDC; - HGDIOBJ saveBmp; - RECT paint_rt; - int i, j; - - /* get window data */ - data = (PNHMapWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); - HDC hFrontBufferDC = BeginPaint(hWnd, &ps); - RECT clientRect; - GetClientRect(hWnd, &clientRect); - + /* stretch back buffer onto front buffer window */ int frontWidth = COLNO * data->xFrontTile; int frontHeight = ROWNO * data->yFrontTile; - int backWidth = COLNO * data->xBackTile; - int backHeight = ROWNO * data->yBackTile; - - HBITMAP hBackBufferBitmap = CreateCompatibleBitmap(hFrontBufferDC, backWidth, backHeight); - HDC hBackBufferDC = CreateCompatibleDC(hFrontBufferDC); - HBITMAP hOldBackBuffer = SelectBitmap(hBackBufferDC, hBackBufferBitmap); - - HDC hRenderDC = hBackBufferDC; - - /* calculate paint rectangle */ - if (!IsRectEmpty(&ps.rcPaint)) { - /* calculate paint rectangle */ - paint_rt.left = 0; - paint_rt.right = COLNO; - paint_rt.top = 0; - paint_rt.bottom = ROWNO; - - if (data->bAsciiMode || Is_rogue_level(&u.uz)) { - /* You enter a VERY primitive world! */ - HGDIOBJ oldFont; - - oldFont = SelectObject(hRenderDC, data->hMapFont); - SetBkMode(hRenderDC, TRANSPARENT); - - /* 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) { - char ch; - WCHAR wch; - RECT glyph_rect; - int color; - unsigned special; - int mgch; - HBRUSH back_brush; - COLORREF OldFg; - - glyph_rect.left = i * data->xBackTile; - glyph_rect.top = j * data->yBackTile; - glyph_rect.right = glyph_rect.left + data->xBackTile; - glyph_rect.bottom = glyph_rect.top + data->yBackTile; - -#if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2) - nhglyph2charcolor(data->map[i][j], &ch, &color); - OldFg = SetTextColor(hDC, nhcolor_to_RGB(color)); -#else - /* rely on NetHack core helper routine */ - (void) mapglyph(data->map[i][j], &mgch, &color, - &special, i, j); - ch = (char) mgch; - if (((special & MG_PET) && iflags.hilite_pet) - || ((special & (MG_DETECT | MG_BW_LAVA)) - && iflags.use_inverse)) { - back_brush = - CreateSolidBrush(nhcolor_to_RGB(CLR_GRAY)); - FillRect(hRenderDC, &glyph_rect, back_brush); - DeleteObject(back_brush); - switch (color) { - case CLR_GRAY: - case CLR_WHITE: - OldFg = SetTextColor( - hRenderDC, nhcolor_to_RGB(CLR_BLACK)); - break; - default: - OldFg = - SetTextColor(hRenderDC, nhcolor_to_RGB(color)); - } - } else { - OldFg = SetTextColor(hRenderDC, nhcolor_to_RGB(color)); - } -#endif - if (data->bUnicodeFont) { - wch = winos_ascii_to_wide(ch); - DrawTextW(hRenderDC, &wch, 1, &glyph_rect, - DT_CENTER | DT_VCENTER | DT_NOPREFIX - | DT_SINGLELINE); - } else { - DrawTextA(hRenderDC, &ch, 1, &glyph_rect, - DT_CENTER | DT_VCENTER | DT_NOPREFIX - | DT_SINGLELINE); - } - - SetTextColor(hRenderDC, OldFg); - } - SelectObject(hRenderDC, oldFont); - } else { - short ntile; - int t_x, t_y; - int glyph, bkglyph; - RECT glyph_rect; - int layer; -#ifdef USE_PILEMARK - int color; - unsigned special; - int mgch; -#endif - /* prepare tiles DC for mapping */ - tileDC = CreateCompatibleDC(hRenderDC); - 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++) { - layer = 0; - glyph = data->map[i][j]; - bkglyph = data->bkmap[i][j]; - - if (bkglyph != NO_GLYPH) { - ntile = glyph2tile[bkglyph]; - t_x = TILEBMP_X(ntile); - t_y = TILEBMP_Y(ntile); - - glyph_rect.left = i * data->xBackTile; - glyph_rect.top = j * data->yBackTile; - glyph_rect.right = glyph_rect.left + data->xBackTile; - glyph_rect.bottom = glyph_rect.top + data->yBackTile; - - StretchBlt(hRenderDC, glyph_rect.left, glyph_rect.top, - data->xBackTile, data->yBackTile, tileDC, - t_x, t_y, GetNHApp()->mapTile_X, - GetNHApp()->mapTile_Y, SRCCOPY); - layer++; - } - - if ((glyph != NO_GLYPH) && (glyph != bkglyph)) { - ntile = glyph2tile[glyph]; - t_x = TILEBMP_X(ntile); - t_y = TILEBMP_Y(ntile); - - glyph_rect.left = i * data->xBackTile; - glyph_rect.top = j * data->yBackTile; - glyph_rect.right = glyph_rect.left + data->xBackTile; - glyph_rect.bottom = glyph_rect.top + data->yBackTile; - - if (layer > 0) { - (*GetNHApp()->lpfnTransparentBlt)( - hRenderDC, glyph_rect.left, glyph_rect.top, - data->xBackTile, data->yBackTile, tileDC, t_x, - t_y, GetNHApp()->mapTile_X, - GetNHApp()->mapTile_Y, TILE_BK_COLOR); - } else { - StretchBlt(hRenderDC, glyph_rect.left, glyph_rect.top, - data->xBackTile, data->yBackTile, tileDC, - t_x, t_y, GetNHApp()->mapTile_X, - GetNHApp()->mapTile_Y, SRCCOPY); - } - - layer++; - } - -#ifdef USE_PILEMARK - /* rely on NetHack core helper routine */ - (void) mapglyph(data->map[i][j], &mgch, &color, &special, - i, j); - if ((glyph != NO_GLYPH) && (special & MG_PET) -#else - if ((glyph != NO_GLYPH) && glyph_is_pet(glyph) -#endif - && iflags.wc_hilite_pet) { - /* apply pet mark transparently over - pet image */ - HDC hdcPetMark; - HBITMAP bmPetMarkOld; - - /* this is DC for petmark bitmap */ - hdcPetMark = CreateCompatibleDC(hRenderDC); - bmPetMarkOld = - SelectObject(hdcPetMark, GetNHApp()->bmpPetMark); - - (*GetNHApp()->lpfnTransparentBlt)( - hRenderDC, glyph_rect.left, glyph_rect.top, - data->xBackTile, data->yBackTile, hdcPetMark, 0, 0, - TILE_X, TILE_Y, TILE_BK_COLOR); - SelectObject(hdcPetMark, bmPetMarkOld); - DeleteDC(hdcPetMark); - } -#ifdef USE_PILEMARK - if ((glyph != NO_GLYPH) && (special & MG_OBJPILE) - && iflags.hilite_pile) { - /* apply pilemark transparently over other image */ - HDC hdcPileMark; - HBITMAP bmPileMarkOld; - - /* this is DC for pilemark bitmap */ - hdcPileMark = CreateCompatibleDC(hRenderDC); - bmPileMarkOld = SelectObject(hdcPileMark, - GetNHApp()->bmpPileMark); - - (*GetNHApp()->lpfnTransparentBlt)( - hRenderDC, glyph_rect.left, glyph_rect.top, - data->xBackTile, data->yBackTile, hdcPileMark, 0, 0, - TILE_X, TILE_Y, TILE_BK_COLOR); - SelectObject(hdcPileMark, bmPileMarkOld); - DeleteDC(hdcPileMark); - } -#endif - } - - SelectObject(tileDC, saveBmp); - DeleteDC(tileDC); - } - - /* draw focus rect */ - paint_rt.left = data->xCur * data->xBackTile; - paint_rt.top = data->yCur * data->yBackTile; - paint_rt.right = paint_rt.left + data->xBackTile; - paint_rt.bottom = paint_rt.top + data->yBackTile; - - if (data->bAsciiMode) { - PatBlt(hRenderDC, paint_rt.left, paint_rt.top, - paint_rt.right - paint_rt.left, - paint_rt.bottom - paint_rt.top, DSTINVERT); - } else { - DrawFocusRect(hRenderDC, &paint_rt); - } - } - StretchBlt(hFrontBufferDC, data->map_orig.x - (data->xPos * data->xFrontTile), data->map_orig.y - (data->yPos * data->yFrontTile), frontWidth, frontHeight, - hBackBufferDC, 0, 0, backWidth, backHeight, SRCCOPY); - - SelectObject(hBackBufferDC, hOldBackBuffer); - DeleteObject(hBackBufferBitmap); - DeleteDC(hBackBufferDC); + data->backBufferDC, 0, 0, data->backWidth, data->backHeight, SRCCOPY); EndPaint(hWnd, &ps); } diff --git a/win/win32/mhmap.h b/win/win32/mhmap.h index cff8a7d5d..695749431 100644 --- a/win/win32/mhmap.h +++ b/win/win32/mhmap.h @@ -15,6 +15,7 @@ void mswin_map_stretch(HWND hWnd, LPSIZE lpsz, BOOL redraw); int mswin_map_mode(HWND hWnd, int mode); #define ROGUE_LEVEL_MAP_MODE MAP_MODE_ASCII12x16 +#define ROGUE_LEVEL_MAP_MODE_FIT_TO_SCREEN MAP_MODE_ASCII_FIT_TO_SCREEN #define DEF_CLIPAROUND_MARGIN 5 #define DEF_CLIPAROUND_AMOUNT 1 diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index fea75b177..c6714bc15 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -813,8 +813,14 @@ mswin_clear_nhwindow(winid wid) && (GetNHApp()->windowlist[wid].win != NULL)) { if (GetNHApp()->windowlist[wid].type == NHW_MAP) { if (Is_rogue_level(&u.uz)) - mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), - ROGUE_LEVEL_MAP_MODE); + if (iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN || + iflags.wc_map_mode == MAP_MODE_TILES_FIT_TO_SCREEN) + + mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), + ROGUE_LEVEL_MAP_MODE_FIT_TO_SCREEN); + else + mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), + ROGUE_LEVEL_MAP_MODE); else mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), iflags.wc_map_mode);