int xPageSize, yPageSize; /* scroll page size */
int xMin, xMax, yMin, yMax; /* scroll range */
int xCur, yCur; /* position of the cursor */
- int xScrTile, yScrTile; /* size of tile on screen in pixels */
+ int xFrontTile, yFrontTile; /* size of tile in front buffer in pixels */
+ int xBackTile, yBackTile; /* size of tile in back buffer in pixels */
POINT map_orig; /* map origin point */
- HFONT hMapFont; /* font for ASCII mode */
- boolean bUnicodeFont; /* font supports unicode page 437 */
+ HFONT hMapFont; /* font for ASCII mode */
+ boolean bUnicodeFont; /* font supports unicode page 437 */
- int tileWidth; /* width of tile in pixels at 96 dpi */
- int tileHeight; /* height of tile in pixels at 96 dpi */
- double scale; /* scale factor */
+ int tileWidth; /* width of tile in pixels at 96 dpi */
+ int tileHeight; /* height of tile in pixels at 96 dpi */
+ double backScale; /* scaling from source to back buffer */
+ double frontScale; /* scaling from back to front */
+ double monitorScale; /* from 96dpi to monitor dpi*/
} NHMapWindow, *PNHMapWindow;
wnd_size.cx = client_rt.right - client_rt.left;
wnd_size.cy = client_rt.bottom - client_rt.top;
- if (wnd_size.cx > 0 && wnd_size.cy > 0 && data->bFitToScreenMode) {
- double windowAspectRatio =
- (double) wnd_size.cx / (double) wnd_size.cy;
- UINT mapWidth = COLNO * data->tileWidth;
- UINT mapHeight = ROWNO * data->tileHeight;
+ /* calculate monitor dpi and monitor scale */
+ UINT monitorDpi = 96;
- double mapAspectRatio = (double) mapWidth / (double) mapHeight;
+ if (gWin10.Valid) {
+ monitorDpi = gWin10.GetDpiForWindow(hWnd);
+ if (monitorDpi == 0)
+ monitorDpi = 96;
+ }
- if (windowAspectRatio > mapAspectRatio)
- data->scale = (double) wnd_size.cy / (double) mapHeight;
- else
- data->scale = (double) wnd_size.cx / (double) mapWidth;
+ monitorDpi = max(96, monitorDpi);
+ data->monitorScale = (double) monitorDpi / 96.0;
+ if (data->bAsciiMode) {
+ data->backScale = data->monitorScale;
} else {
- // Auto size window
+ data->backScale = 1.0;
+ }
+
+ /* set back buffer tile size */
+ data->xBackTile = (int) (data->tileWidth * data->backScale);
+ data->yBackTile = (int) (data->tileHeight * data->backScale);
+
+ if (data->bAsciiMode) {
- UINT windowDpi = 96;
+ /* create font */
+ if (data->hMapFont)
+ DeleteObject(data->hMapFont);
- if (gWin10.Valid) {
- windowDpi = gWin10.GetDpiForWindow(hWnd);
- if (windowDpi == 0)
- windowDpi = 96;
+ LOGFONT lgfnt;
+
+ ZeroMemory(&lgfnt, sizeof(lgfnt));
+ lgfnt.lfHeight = -data->yBackTile; // height of font
+ lgfnt.lfWidth = -data->xBackTile; // average character width
+ lgfnt.lfEscapement = 0; // angle of escapement
+ lgfnt.lfOrientation = 0; // base-line orientation angle
+ lgfnt.lfWeight = FW_NORMAL; // font weight
+ lgfnt.lfItalic = FALSE; // italic attribute option
+ lgfnt.lfUnderline = FALSE; // underline attribute option
+ lgfnt.lfStrikeOut = FALSE; // strikeout attribute option
+ lgfnt.lfCharSet = mswin_charset(); // character set identifier
+ lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision
+ lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
+ lgfnt.lfQuality = NONANTIALIASED_QUALITY; // output quality
+ if (iflags.wc_font_map && *iflags.wc_font_map) {
+ lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
+ NH_A2W(iflags.wc_font_map, lgfnt.lfFaceName, LF_FACESIZE);
+ } else {
+ lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
+ NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE);
}
- windowDpi = max(96, windowDpi);
- data->scale = (double) windowDpi / 96.0;
- }
+ TEXTMETRIC textMetrics;
- /* set new screen tile size */
- data->xScrTile = (int) (data->tileWidth * data->scale);
- data->yScrTile = (int) (data->tileHeight * data->scale);
-
- data->xScrTile = max(1, data->xScrTile);
- data->yScrTile = max(1, data->yScrTile);
-
- /* create font */
- if (data->hMapFont)
- DeleteObject(data->hMapFont);
-
- LOGFONT lgfnt;
-
- ZeroMemory(&lgfnt, sizeof(lgfnt));
- lgfnt.lfHeight = -data->yScrTile; // height of font
- lgfnt.lfWidth = -data->xScrTile; // average character width
- lgfnt.lfEscapement = 0; // angle of escapement
- lgfnt.lfOrientation = 0; // base-line orientation angle
- lgfnt.lfWeight = FW_NORMAL; // font weight
- lgfnt.lfItalic = FALSE; // italic attribute option
- lgfnt.lfUnderline = FALSE; // underline attribute option
- lgfnt.lfStrikeOut = FALSE; // strikeout attribute option
- lgfnt.lfCharSet = mswin_charset(); // character set identifier
- lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision
- lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
- lgfnt.lfQuality = NONANTIALIASED_QUALITY; // output quality
- if (iflags.wc_font_map && *iflags.wc_font_map) {
- lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
- NH_A2W(iflags.wc_font_map, lgfnt.lfFaceName, LF_FACESIZE);
- } else {
- lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
- NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE);
- }
+ while (1) {
+ data->hMapFont = CreateFontIndirect(&lgfnt);
- TEXTMETRIC textMetrics;
+ HDC hdc = GetDC(NULL);
+ HFONT savedFont = SelectObject(hdc, data->hMapFont);
- while (1) {
- data->hMapFont = CreateFontIndirect(&lgfnt);
+ GetTextMetrics(hdc, &textMetrics);
- HDC hdc = GetDC(NULL);
- HFONT savedFont = SelectObject(hdc, data->hMapFont);
+ SelectObject(hdc, savedFont);
+ ReleaseDC(NULL, hdc);
- GetTextMetrics(hdc, &textMetrics);
+ if (textMetrics.tmHeight > data->yBackTile) {
+ lgfnt.lfHeight++;
+ continue;
+ }
- SelectObject(hdc, savedFont);
- ReleaseDC(NULL, hdc);
+ if (textMetrics.tmAveCharWidth > data->xBackTile) {
+ lgfnt.lfWidth++;
+ continue;
+ }
- if (textMetrics.tmHeight > data->yScrTile) {
- lgfnt.lfHeight++;
- continue;
+ break;
}
- if (textMetrics.tmAveCharWidth > data->xScrTile) {
- lgfnt.lfWidth++;
- continue;
- }
+ data->bUnicodeFont = winos_font_support_cp437(data->hMapFont);
+
+ // set tile size to match font metrics
+
+ data->xBackTile = textMetrics.tmAveCharWidth;
+ data->yBackTile = textMetrics.tmHeight;
- break;
}
- data->bUnicodeFont = winos_font_support_cp437(data->hMapFont);
+ /* calculate front buffer tile size */
- // set tile size to match font metrics
+ 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;
+
+ if (windowAspectRatio > backAspectRatio)
+ data->frontScale = (double) wnd_size.cy / (double) backHeight;
+ else
+ data->frontScale = (double) wnd_size.cx / (double) backWidth;
+
+ } else {
+
+ if (data->bAsciiMode) {
+ data->frontScale = 1.0;
+ } else {
+ data->frontScale = data->monitorScale;
+ }
- if (data->bAsciiMode) {
- data->xScrTile = textMetrics.tmAveCharWidth;
- data->yScrTile = textMetrics.tmHeight;
}
+ data->xFrontTile = (int) ((double) data->xBackTile * data->frontScale);
+ data->yFrontTile = (int) ((double) data->yBackTile * data->frontScale);
+
/* set map origin point */
data->map_orig.x =
- max(0, client_rt.left + (wnd_size.cx - data->xScrTile * COLNO) / 2);
+ max(0, client_rt.left + (wnd_size.cx - data->xFrontTile * COLNO) / 2);
data->map_orig.y =
- max(0, client_rt.top + (wnd_size.cy - data->yScrTile * ROWNO) / 2);
+ max(0, client_rt.top + (wnd_size.cy - data->yFrontTile * ROWNO) / 2);
- data->map_orig.x -= data->map_orig.x % data->xScrTile;
- data->map_orig.y -= data->map_orig.y % data->yScrTile;
+ data->map_orig.x -= data->map_orig.x % data->xFrontTile;
+ data->map_orig.y -= data->map_orig.y % data->yFrontTile;
// Set horizontal scroll
- data->xPageSize = min(COLNO, wnd_size.cx / data->xScrTile);
+ data->xPageSize = min(COLNO, wnd_size.cx / data->xFrontTile);
GetNHApp()->bNoHScroll = (data->xPageSize == COLNO);
si.nPos = data->xPos;
SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
- data->yPageSize = min(ROWNO, wnd_size.cy / data->yScrTile);
+ data->yPageSize = min(ROWNO, wnd_size.cy / data->yFrontTile);
GetNHApp()->bNoVScroll = (data->yPageSize == ROWNO);
} else {
/* mapping factor is unchaged we just need to adjust scroll bars
*/
- size.cx = data->xScrTile * COLNO;
- size.cy = data->yScrTile * ROWNO;
+ size.cx = data->xFrontTile * COLNO;
+ size.cy = data->yFrontTile * ROWNO;
}
mswin_map_stretch(hWnd, &size, TRUE);
NHEVENT_MS(CLICK_1,
max(0, min(COLNO, data->xPos
+ (LOWORD(lParam) - data->map_orig.x)
- / data->xScrTile)),
+ / data->xFrontTile)),
max(0, min(ROWNO, data->yPos
+ (HIWORD(lParam) - data->map_orig.y)
- / data->yScrTile)));
+ / data->yFrontTile)));
return 0;
case WM_LBUTTONDBLCLK:
NHEVENT_MS(CLICK_2,
max(0, min(COLNO, data->xPos
+ (LOWORD(lParam) - data->map_orig.x)
- / data->xScrTile)),
+ / data->xFrontTile)),
max(0, min(ROWNO, data->yPos
+ (HIWORD(lParam) - data->map_orig.y)
- / data->yScrTile)));
+ / data->yFrontTile)));
return 0;
case WM_DESTROY:
data->bAsciiMode = FALSE;
- data->xScrTile = GetNHApp()->mapTile_X;
- data->yScrTile = GetNHApp()->mapTile_Y;
+ data->xFrontTile = GetNHApp()->mapTile_X;
+ data->yFrontTile = GetNHApp()->mapTile_Y;
data->tileWidth = GetNHApp()->mapTile_X;
data->tileHeight = GetNHApp()->mapTile_Y;
{
PNHMapWindow data;
PAINTSTRUCT ps;
- HDC hDC;
HDC tileDC;
HGDIOBJ saveBmp;
RECT paint_rt;
/* get window data */
data = (PNHMapWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
- hDC = BeginPaint(hWnd, &ps);
+ HDC hFrontBufferDC = BeginPaint(hWnd, &ps);
+
+ RECT clientRect;
+ GetClientRect(hWnd, &clientRect);
+
+ 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 =
- max(data->xPos
- + (ps.rcPaint.left - data->map_orig.x) / data->xScrTile,
- 0);
- paint_rt.top = max(
- data->yPos + (ps.rcPaint.top - data->map_orig.y) / data->yScrTile,
- 0);
- paint_rt.right = min(
- data->xPos
- + (ps.rcPaint.right - data->map_orig.x) / data->xScrTile + 1,
- COLNO);
- paint_rt.bottom = min(
- data->yPos
- + (ps.rcPaint.bottom - data->map_orig.y) / data->yScrTile + 1,
- ROWNO);
+ 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(hDC, data->hMapFont);
- SetBkMode(hDC, TRANSPARENT);
+ oldFont = SelectObject(hRenderDC, data->hMapFont);
+ SetBkMode(hRenderDC, TRANSPARENT);
/* draw the map */
for (i = paint_rt.left; i < paint_rt.right; i++)
HBRUSH back_brush;
COLORREF OldFg;
- nhcoord2display(data, i, j, &glyph_rect);
+ 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);
&& iflags.use_inverse)) {
back_brush =
CreateSolidBrush(nhcolor_to_RGB(CLR_GRAY));
- FillRect(hDC, &glyph_rect, back_brush);
+ FillRect(hRenderDC, &glyph_rect, back_brush);
DeleteObject(back_brush);
switch (color) {
case CLR_GRAY:
case CLR_WHITE:
OldFg = SetTextColor(
- hDC, nhcolor_to_RGB(CLR_BLACK));
+ hRenderDC, nhcolor_to_RGB(CLR_BLACK));
break;
default:
OldFg =
- SetTextColor(hDC, nhcolor_to_RGB(color));
+ SetTextColor(hRenderDC, nhcolor_to_RGB(color));
}
} else {
- OldFg = SetTextColor(hDC, nhcolor_to_RGB(color));
+ OldFg = SetTextColor(hRenderDC, nhcolor_to_RGB(color));
}
#endif
if (data->bUnicodeFont) {
wch = winos_ascii_to_wide(ch);
- DrawTextW(hDC, &wch, 1, &glyph_rect,
+ DrawTextW(hRenderDC, &wch, 1, &glyph_rect,
DT_CENTER | DT_VCENTER | DT_NOPREFIX
| DT_SINGLELINE);
} else {
- DrawTextA(hDC, &ch, 1, &glyph_rect,
+ DrawTextA(hRenderDC, &ch, 1, &glyph_rect,
DT_CENTER | DT_VCENTER | DT_NOPREFIX
| DT_SINGLELINE);
}
- SetTextColor(hDC, OldFg);
+ SetTextColor(hRenderDC, OldFg);
}
- SelectObject(hDC, oldFont);
+ SelectObject(hRenderDC, oldFont);
} else {
short ntile;
int t_x, t_y;
int mgch;
#endif
/* prepare tiles DC for mapping */
- tileDC = CreateCompatibleDC(hDC);
+ tileDC = CreateCompatibleDC(hRenderDC);
saveBmp = SelectObject(tileDC, GetNHApp()->bmpMapTiles);
/* draw the map */
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,
+ 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++;
ntile = glyph2tile[glyph];
t_x = TILEBMP_X(ntile);
t_y = TILEBMP_Y(ntile);
- nhcoord2display(data, i, j, &glyph_rect);
+
+ 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)(
- hDC, glyph_rect.left, glyph_rect.top,
- data->xScrTile, data->yScrTile, tileDC, t_x,
+ 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(hDC, glyph_rect.left, glyph_rect.top,
- data->xScrTile, data->yScrTile, tileDC,
+ StretchBlt(hRenderDC, glyph_rect.left, glyph_rect.top,
+ data->xBackTile, data->yBackTile, tileDC,
t_x, t_y, GetNHApp()->mapTile_X,
GetNHApp()->mapTile_Y, SRCCOPY);
}
HBITMAP bmPetMarkOld;
/* this is DC for petmark bitmap */
- hdcPetMark = CreateCompatibleDC(hDC);
+ hdcPetMark = CreateCompatibleDC(hRenderDC);
bmPetMarkOld =
SelectObject(hdcPetMark, GetNHApp()->bmpPetMark);
(*GetNHApp()->lpfnTransparentBlt)(
- hDC, glyph_rect.left, glyph_rect.top,
- data->xScrTile, data->yScrTile, hdcPetMark, 0, 0,
+ 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);
HBITMAP bmPileMarkOld;
/* this is DC for pilemark bitmap */
- hdcPileMark = CreateCompatibleDC(hDC);
+ hdcPileMark = CreateCompatibleDC(hRenderDC);
bmPileMarkOld = SelectObject(hdcPileMark,
GetNHApp()->bmpPileMark);
(*GetNHApp()->lpfnTransparentBlt)(
- hDC, glyph_rect.left, glyph_rect.top,
- data->xScrTile, data->yScrTile, hdcPileMark, 0, 0,
+ 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);
}
/* draw focus rect */
- nhcoord2display(data, data->xCur, data->yCur, &paint_rt);
+ 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(hDC, paint_rt.left, paint_rt.top,
+ PatBlt(hRenderDC, paint_rt.left, paint_rt.top,
paint_rt.right - paint_rt.left,
paint_rt.bottom - paint_rt.top, DSTINVERT);
} else {
- DrawFocusRect(hDC, &paint_rt);
+ 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);
+
EndPaint(hWnd, &ps);
}
yDelta = yNewPos - data->yPos;
data->yPos = yNewPos;
- ScrollWindowEx(hWnd, 0, -data->yScrTile * yDelta, (CONST RECT *) NULL,
+ ScrollWindowEx(hWnd, 0, -data->yFrontTile * yDelta, (CONST RECT *) NULL,
(CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
SW_INVALIDATE | SW_ERASE);
xDelta = xNewPos - data->xPos;
data->xPos = xNewPos;
- ScrollWindowEx(hWnd, -data->xScrTile * xDelta, 0, (CONST RECT *) NULL,
+ ScrollWindowEx(hWnd, -data->xFrontTile * xDelta, 0, (CONST RECT *) NULL,
(CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
SW_INVALIDATE | SW_ERASE);
void
nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut)
{
- lpOut->left = (x - data->xPos) * data->xScrTile + data->map_orig.x;
- lpOut->top = (y - data->yPos) * data->yScrTile + data->map_orig.y;
- lpOut->right = lpOut->left + data->xScrTile;
- lpOut->bottom = lpOut->top + data->yScrTile;
+ lpOut->left = (x - data->xPos) * data->xFrontTile + data->map_orig.x;
+ lpOut->top = (y - data->yPos) * data->yFrontTile + data->map_orig.y;
+ lpOut->right = lpOut->left + data->xFrontTile;
+ lpOut->bottom = lpOut->top + data->yFrontTile;
}
#if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2)