From 2f856f6f0d1a2053deec61fb8fa282a80b56210d Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Fri, 16 Jun 2023 08:05:23 +0900 Subject: [PATCH] [MSPAINT] Add CachedBufferDIB function and use it We do caching on buffering paint. This will improve performance a little. CORE-18867 --- base/applications/mspaint/canvas.cpp | 13 ++++++++++--- base/applications/mspaint/canvas.h | 2 ++ base/applications/mspaint/dib.cpp | 20 ++++++++++++++++++++ base/applications/mspaint/dib.h | 1 + base/applications/mspaint/miniature.cpp | 16 ++++++++++++++-- base/applications/mspaint/miniature.h | 7 ++++++- base/applications/mspaint/palette.cpp | 17 ++++++++++++++--- base/applications/mspaint/palette.h | 6 ++++++ 8 files changed, 73 insertions(+), 9 deletions(-) diff --git a/base/applications/mspaint/canvas.cpp b/base/applications/mspaint/canvas.cpp index b83a692ab7c..c36bd76faed 100644 --- a/base/applications/mspaint/canvas.cpp +++ b/base/applications/mspaint/canvas.cpp @@ -17,10 +17,17 @@ CCanvasWindow::CCanvasWindow() , m_hitSelection(HIT_NONE) , m_whereHit(HIT_NONE) , m_ptOrig { -1, -1 } + , m_hbmCached(NULL) { ::SetRectEmpty(&m_rcNew); } +CCanvasWindow::~CCanvasWindow() +{ + if (m_hbmCached) + ::DeleteObject(m_hbmCached); +} + VOID CCanvasWindow::drawZoomFrame(INT mouseX, INT mouseY) { // FIXME: Draw the border of the area that is to be zoomed in @@ -95,8 +102,8 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint) { // We use a memory bitmap to reduce flickering HDC hdcMem = ::CreateCompatibleDC(hDC); - HBITMAP hbm = ::CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom); - HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbm); + m_hbmCached = CachedBufferDIB(m_hbmCached, rcClient.right, rcClient.bottom); + HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmCached); // Fill the background ::FillRect(hdcMem, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1)); @@ -164,7 +171,7 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint) rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top, hdcMem, rcPaint.left, rcPaint.top, SRCCOPY); - ::DeleteObject(::SelectObject(hdcMem, hbmOld)); + ::SelectObject(hdcMem, hbmOld); ::DeleteDC(hdcMem); } diff --git a/base/applications/mspaint/canvas.h b/base/applications/mspaint/canvas.h index 53d5fa1acc1..d76b3761b9c 100644 --- a/base/applications/mspaint/canvas.h +++ b/base/applications/mspaint/canvas.h @@ -36,6 +36,7 @@ public: END_MSG_MAP() CCanvasWindow(); + virtual ~CCanvasWindow(); BOOL m_drawing; @@ -54,6 +55,7 @@ protected: CANVAS_HITTEST m_hitSelection; CANVAS_HITTEST m_whereHit; POINT m_ptOrig; // The origin of drag start + HBITMAP m_hbmCached; // The cached buffer bitmap CRect m_rcNew; CANVAS_HITTEST CanvasHitTest(POINT pt); diff --git a/base/applications/mspaint/dib.cpp b/base/applications/mspaint/dib.cpp index 3d74403cdda..1e7477c661e 100644 --- a/base/applications/mspaint/dib.cpp +++ b/base/applications/mspaint/dib.cpp @@ -59,6 +59,26 @@ CreateColorDIB(int width, int height, COLORREF rgb) return ret; } +HBITMAP CachedBufferDIB(HBITMAP hbm, int minimalWidth, int minimalHeight) +{ + if (minimalWidth <= 0) + minimalWidth = 1; + if (minimalHeight <= 0) + minimalHeight = 1; + + BITMAP bm; + if (!GetObject(hbm, sizeof(bm), &bm)) + hbm = NULL; + + if (hbm && minimalWidth <= bm.bmWidth && minimalHeight <= bm.bmHeight) + return hbm; + + if (hbm) + DeleteObject(hbm); + + return CreateDIBWithProperties((minimalWidth * 3) / 2, (minimalHeight * 3) / 2); +} + int GetDIBWidth(HBITMAP hBitmap) { diff --git a/base/applications/mspaint/dib.h b/base/applications/mspaint/dib.h index cc873913114..f4043d83ca3 100644 --- a/base/applications/mspaint/dib.h +++ b/base/applications/mspaint/dib.h @@ -10,6 +10,7 @@ HBITMAP CreateDIBWithProperties(int width, int height); HBITMAP CreateColorDIB(int width, int height, COLORREF rgb); +HBITMAP CachedBufferDIB(HBITMAP hbm, int minimalWidth, int minimalHeight); static inline HBITMAP CopyDIBImage(HBITMAP hbm, INT cx = 0, INT cy = 0) { diff --git a/base/applications/mspaint/miniature.cpp b/base/applications/mspaint/miniature.cpp index 223b38e176a..b354de983b1 100644 --- a/base/applications/mspaint/miniature.cpp +++ b/base/applications/mspaint/miniature.cpp @@ -14,6 +14,17 @@ CMiniatureWindow miniature; /* FUNCTIONS ********************************************************/ +CMiniatureWindow::CMiniatureWindow() + : m_hbmCached(NULL) +{ +} + +CMiniatureWindow::~CMiniatureWindow() +{ + if (m_hbmCached) + ::DeleteObject(m_hbmCached); +} + HWND CMiniatureWindow::DoCreate(HWND hwndParent) { if (m_hWnd) @@ -82,7 +93,8 @@ LRESULT CMiniatureWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& // Use a memory bitmap to reduce flickering HDC hdcMem = ::CreateCompatibleDC(hDC); - HGDIOBJ hbmOld = ::SelectObject(hdcMem, ::CreateCompatibleBitmap(hDC, rc.right, rc.bottom)); + m_hbmCached = CachedBufferDIB(m_hbmCached, rc.right, rc.bottom); + HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmCached); // FIXME: Consider aspect ratio @@ -100,7 +112,7 @@ LRESULT CMiniatureWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& ::BitBlt(hDC, 0, 0, rc.right, rc.bottom, hdcMem, 0, 0, SRCCOPY); // Clean up - ::DeleteObject(::SelectObject(hdcMem, hbmOld)); + ::SelectObject(hdcMem, hbmOld); ::DeleteDC(hdcMem); EndPaint(&ps); diff --git a/base/applications/mspaint/miniature.h b/base/applications/mspaint/miniature.h index e1ec6657f88..9c01f1b9091 100644 --- a/base/applications/mspaint/miniature.h +++ b/base/applications/mspaint/miniature.h @@ -24,9 +24,14 @@ public: MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo) END_MSG_MAP() + CMiniatureWindow(); + virtual ~CMiniatureWindow(); + HWND DoCreate(HWND hwndParent); -private: +protected: + HBITMAP m_hbmCached; // Cached buffer bitmap + LRESULT OnMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); diff --git a/base/applications/mspaint/palette.cpp b/base/applications/mspaint/palette.cpp index acd5552defc..f268a982f49 100644 --- a/base/applications/mspaint/palette.cpp +++ b/base/applications/mspaint/palette.cpp @@ -21,6 +21,17 @@ CPaletteWindow paletteWindow; /* FUNCTIONS ********************************************************/ +CPaletteWindow::CPaletteWindow() + : m_hbmCached(NULL) +{ +} + +CPaletteWindow::~CPaletteWindow() +{ + if (m_hbmCached) + ::DeleteObject(m_hbmCached); +} + static VOID drawColorBox(HDC hDC, LPCRECT prc, COLORREF rgbColor, UINT nBorder) { RECT rc = *prc; @@ -76,8 +87,8 @@ LRESULT CPaletteWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& b /* To avoid flickering, we use a memory bitmap. The left and top values are zeros in client rectangle */ HDC hMemDC = ::CreateCompatibleDC(hDC); - HBITMAP hbm = ::CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom); - HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbm); + m_hbmCached = CachedBufferDIB(m_hbmCached, rcClient.right, rcClient.bottom); + HGDIOBJ hbmOld = ::SelectObject(hMemDC, m_hbmCached); /* Fill the background (since WM_ERASEBKGND handling is disabled) */ ::FillRect(hMemDC, &rcClient, (HBRUSH)(COLOR_3DFACE + 1)); @@ -121,7 +132,7 @@ LRESULT CPaletteWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& b /* Transfer bits (hDC <-- hMemDC) */ ::BitBlt(hDC, 0, 0, rcClient.right, rcClient.bottom, hMemDC, 0, 0, SRCCOPY); - ::DeleteObject(::SelectObject(hMemDC, hbmOld)); + ::SelectObject(hMemDC, hbmOld); ::DeleteDC(hMemDC); EndPaint(&ps); return 0; diff --git a/base/applications/mspaint/palette.h b/base/applications/mspaint/palette.h index c9e09e92708..fe23edda53f 100644 --- a/base/applications/mspaint/palette.h +++ b/base/applications/mspaint/palette.h @@ -30,6 +30,12 @@ public: MESSAGE_HANDLER(WM_PALETTEMODELPALETTECHANGED, OnPaletteModelPaletteChanged) END_MSG_MAP() + CPaletteWindow(); + virtual ~CPaletteWindow(); + +protected: + HBITMAP m_hbmCached; // Cached buffer bitmap + LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);