[MSPAINT] Calculate intersection to reduce bits transfer (#5795)

Drawing lines smoothly on big image.
- In CCanvasWindow::DoDraw, calculate the
  intersection to reduce bits transfer.
- Improve SmoothDrawTool in handling Shift key.
CORE-19094, CORE-19237
This commit is contained in:
Katayama Hirofumi MZ 2023-10-16 09:09:40 +09:00 committed by GitHub
parent 5c2ec83fa7
commit fd1e158480
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 17 deletions

View file

@ -91,29 +91,43 @@ HITTEST CCanvasWindow::CanvasHitTest(POINT pt)
VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint) VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
{ {
// This is the target area we have to draw on
CRect rcCanvasDraw;
rcCanvasDraw.IntersectRect(&rcClient, &rcPaint);
// We use a memory bitmap to reduce flickering // We use a memory bitmap to reduce flickering
HDC hdcMem0 = ::CreateCompatibleDC(hDC); HDC hdcMem0 = ::CreateCompatibleDC(hDC);
m_ahbmCached[0] = CachedBufferDIB(m_ahbmCached[0], rcClient.right, rcClient.bottom); m_ahbmCached[0] = CachedBufferDIB(m_ahbmCached[0], rcClient.right, rcClient.bottom);
HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, m_ahbmCached[0]); HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, m_ahbmCached[0]);
// Fill the background on hdcMem0 // Fill the background on hdcMem0
::FillRect(hdcMem0, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1)); ::FillRect(hdcMem0, &rcCanvasDraw, (HBRUSH)(COLOR_APPWORKSPACE + 1));
// Draw the sizeboxes if necessary // Draw the sizeboxes if necessary
RECT rcBase = GetBaseRect(); RECT rcBase = GetBaseRect();
if (!selectionModel.m_bShow && !::IsWindowVisible(textEditWindow)) if (!selectionModel.m_bShow && !::IsWindowVisible(textEditWindow))
drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcPaint); drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcCanvasDraw);
// Calculate image size // Calculate image size
CRect rcImage; CRect rcImage;
GetImageRect(rcImage); GetImageRect(rcImage);
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() }; SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
// Calculate the target area on the image
CRect rcImageDraw = rcCanvasDraw;
CanvasToImage(rcImageDraw);
rcImageDraw.IntersectRect(&rcImageDraw, &rcImage);
// Consider rounding down by zooming
rcImageDraw.right += 1;
rcImageDraw.bottom += 1;
// hdcMem1 <-- imageModel // hdcMem1 <-- imageModel
HDC hdcMem1 = ::CreateCompatibleDC(hDC); HDC hdcMem1 = ::CreateCompatibleDC(hDC);
m_ahbmCached[1] = CachedBufferDIB(m_ahbmCached[1], sizeImage.cx, sizeImage.cy); m_ahbmCached[1] = CachedBufferDIB(m_ahbmCached[1], sizeImage.cx, sizeImage.cy);
HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, m_ahbmCached[1]); HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, m_ahbmCached[1]);
BitBlt(hdcMem1, 0, 0, sizeImage.cx, sizeImage.cy, imageModel.GetDC(), 0, 0, SRCCOPY); ::BitBlt(hdcMem1, rcImageDraw.left, rcImageDraw.top, rcImageDraw.Width(), rcImageDraw.Height(),
imageModel.GetDC(), rcImageDraw.left, rcImageDraw.top, SRCCOPY);
// Draw overlay #1 on hdcMem1 // Draw overlay #1 on hdcMem1
toolsModel.OnDrawOverlayOnImage(hdcMem1); toolsModel.OnDrawOverlayOnImage(hdcMem1);
@ -158,10 +172,8 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
DrawXorRect(hdcMem0, &m_rcResizing); DrawXorRect(hdcMem0, &m_rcResizing);
// Transfer the bits (hDC <-- hdcMem0) // Transfer the bits (hDC <-- hdcMem0)
::BitBlt(hDC, ::BitBlt(hDC, rcCanvasDraw.left, rcCanvasDraw.top, rcCanvasDraw.Width(), rcCanvasDraw.Height(),
rcPaint.left, rcPaint.top, hdcMem0, rcCanvasDraw.left, rcCanvasDraw.top, SRCCOPY);
rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top,
hdcMem0, rcPaint.left, rcPaint.top, SRCCOPY);
// Clean up hdcMem0 // Clean up hdcMem0
::SelectObject(hdcMem0, hbm0Old); ::SelectObject(hdcMem0, hbm0Old);

View file

@ -421,6 +421,7 @@ RestrictDrawDirection(DIRECTION dir, LONG x0, LONG y0, LONG& x1, LONG& y1)
struct SmoothDrawTool : ToolBase struct SmoothDrawTool : ToolBase
{ {
DIRECTION m_direction = NO_DIRECTION; DIRECTION m_direction = NO_DIRECTION;
BOOL m_bShiftDown = FALSE;
SmoothDrawTool(TOOLTYPE type) : ToolBase(type) SmoothDrawTool(TOOLTYPE type) : ToolBase(type)
{ {
@ -433,11 +434,12 @@ struct SmoothDrawTool : ToolBase
m_direction = NO_DIRECTION; m_direction = NO_DIRECTION;
imageModel.PushImageForUndo(); imageModel.PushImageForUndo();
imageModel.NotifyImageChanged(); imageModel.NotifyImageChanged();
m_bShiftDown = (::GetKeyState(VK_SHIFT) & 0x8000); // Is Shift key pressed?
} }
BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{ {
if (::GetKeyState(VK_SHIFT) < 0) // Shift key is pressed if (m_bShiftDown)
{ {
if (m_direction == NO_DIRECTION) if (m_direction == NO_DIRECTION)
{ {
@ -450,15 +452,11 @@ struct SmoothDrawTool : ToolBase
} }
else else
{ {
if (m_direction != NO_DIRECTION)
{
m_direction = NO_DIRECTION;
draw(bLeftButton, x, y); draw(bLeftButton, x, y);
g_ptStart.x = g_ptEnd.x = x; g_ptStart.x = g_ptEnd.x = x;
g_ptStart.y = g_ptEnd.y = y; g_ptStart.y = g_ptEnd.y = y;
return TRUE; return TRUE;
} }
}
draw(bLeftButton, x, y); draw(bLeftButton, x, y);
imageModel.NotifyImageChanged(); imageModel.NotifyImageChanged();
@ -467,7 +465,7 @@ struct SmoothDrawTool : ToolBase
BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{ {
if (m_direction != NO_DIRECTION) if (m_bShiftDown && m_direction != NO_DIRECTION)
{ {
RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y); RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y);
} }