https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b8598e095d313bffd8169bd1ca8c1ee7b22026bd

commit b8598e095d313bffd8169bd1ca8c1ee7b22026bd
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Nov 25 13:44:31 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Nov 25 13:44:31 2023 +0900

    [MSPAINT] Improve Undo/Redo handling of selection (#6035)
    
    Consistent behavior of the application.
    - Add ShiftPtStack and BuildMaskFromPtStack
      helper functions.
    - Move some codes of selectionModel to
      mouse.cpp.
    CORE-19226
---
 base/applications/mspaint/canvas.cpp         |  17 +---
 base/applications/mspaint/canvas.h           |   3 +-
 base/applications/mspaint/history.cpp        |  20 ++---
 base/applications/mspaint/history.h          |   1 -
 base/applications/mspaint/main.cpp           |  36 ++------
 base/applications/mspaint/mouse.cpp          | 128 +++++++++++++++++++--------
 base/applications/mspaint/selectionmodel.cpp | 120 +++++--------------------
 base/applications/mspaint/selectionmodel.h   |  10 +--
 base/applications/mspaint/toolsmodel.cpp     |   3 +
 base/applications/mspaint/toolsmodel.h       |   1 -
 10 files changed, 134 insertions(+), 205 deletions(-)

diff --git a/base/applications/mspaint/canvas.cpp 
b/base/applications/mspaint/canvas.cpp
index fa6201cdf21..06074cf0c45 100644
--- a/base/applications/mspaint/canvas.cpp
+++ b/base/applications/mspaint/canvas.cpp
@@ -648,9 +648,9 @@ LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL
 
 LRESULT CCanvasWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
 {
-    if (wParam == VK_ESCAPE && ::GetCapture() == m_hWnd)
+    if (wParam == VK_ESCAPE)
     {
-        cancelDrawing();
+        OnEndDraw(TRUE);
         ::ReleaseCapture();
         m_nMouseDownMsg = 0;
         m_hitCanvasSizeBox = HIT_NONE;
@@ -698,19 +698,10 @@ LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
     return 0;
 }
 
-VOID CCanvasWindow::cancelDrawing()
+VOID CCanvasWindow::OnEndDraw(BOOL bCancel)
 {
-    selectionModel.ClearColorImage();
-    selectionModel.ClearMaskImage();
-    m_drawing = FALSE;
-    toolsModel.OnEndDraw(TRUE);
-    Invalidate(FALSE);
-}
-
-VOID CCanvasWindow::finishDrawing()
-{
-    toolsModel.OnEndDraw(FALSE);
     m_drawing = FALSE;
+    toolsModel.OnEndDraw(bCancel);
     Invalidate(FALSE);
 }
 
diff --git a/base/applications/mspaint/canvas.h 
b/base/applications/mspaint/canvas.h
index 5bdd1def467..ef0323df65f 100644
--- a/base/applications/mspaint/canvas.h
+++ b/base/applications/mspaint/canvas.h
@@ -42,8 +42,7 @@ public:
 
     BOOL m_drawing;
 
-    VOID cancelDrawing();
-    VOID finishDrawing();
+    VOID OnEndDraw(BOOL bCancel);
     VOID updateScrollRange();
     VOID updateScrollPos(INT x = 0, INT y = 0);
 
diff --git a/base/applications/mspaint/history.cpp 
b/base/applications/mspaint/history.cpp
index 696e02656c2..c7b32cc5ab4 100644
--- a/base/applications/mspaint/history.cpp
+++ b/base/applications/mspaint/history.cpp
@@ -164,8 +164,13 @@ void ImageModel::PushImageForUndo(const RECT& rcPartial)
     part.m_bPartial = TRUE;
     part.m_rcPart = rcPartial;
 
+    CRect rcImage = { 0, 0, GetWidth(), GetHeight() };
+    CRect& rc = part.m_rcPart;
+    if (!rc.IntersectRect(rc, rcImage))
+        rc.SetRect(-1, -1, 0, 0);
+
     HBITMAP hbmMaster = LockBitmap();
-    part.m_hbmImage = getSubImage(hbmMaster, rcPartial);
+    part.m_hbmImage = getSubImage(hbmMaster, rc);
     UnlockBitmap(hbmMaster);
 
     PushDone();
@@ -351,16 +356,3 @@ void ImageModel::UnlockBitmap(HBITMAP hbmLocked)
     m_hbmMaster = hbmLocked;
     m_hbmOld = ::SelectObject(m_hDrawingDC, m_hbmMaster); // Re-select
 }
-
-void ImageModel::SelectionClone(BOOL bUndoable)
-{
-    if (!selectionModel.m_bShow || selectionModel.m_rc.IsRectEmpty())
-        return;
-
-    if (bUndoable)
-        PushImageForUndo();
-
-    selectionModel.DrawSelection(m_hDrawingDC, paletteModel.GetBgColor(),
-                                 toolsModel.IsBackgroundTransparent());
-    NotifyImageChanged();
-}
diff --git a/base/applications/mspaint/history.h 
b/base/applications/mspaint/history.h
index 87c98515136..7dc949b31f4 100644
--- a/base/applications/mspaint/history.h
+++ b/base/applications/mspaint/history.h
@@ -51,7 +51,6 @@ public:
     void NotifyImageChanged();
     BOOL IsBlackAndWhite();
     void PushBlackAndWhite();
-    void SelectionClone(BOOL bUndoable = TRUE);
 
 protected:
     HDC m_hDrawingDC; // The device context for this class
diff --git a/base/applications/mspaint/main.cpp 
b/base/applications/mspaint/main.cpp
index 7e3364678f1..c93a41a886a 100644
--- a/base/applications/mspaint/main.cpp
+++ b/base/applications/mspaint/main.cpp
@@ -406,7 +406,7 @@ void CMainWindow::alignChildrenToMainWindow()
 
 void CMainWindow::saveImage(BOOL overwrite)
 {
-    canvasWindow.finishDrawing();
+    canvasWindow.OnEndDraw(FALSE);
 
     // Is the extension not supported?
     PWCHAR pchDotExt = PathFindExtensionW(g_szFileName);
@@ -606,7 +606,7 @@ LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
 
 BOOL CMainWindow::ConfirmSave()
 {
-    canvasWindow.finishDrawing();
+    canvasWindow.OnEndDraw(FALSE);
 
     if (imageModel.IsImageSaved())
         return TRUE;
@@ -693,8 +693,6 @@ BOOL CMainWindow::CanUndo() const
         return (BOOL)textEditWindow.SendMessage(EM_CANUNDO);
     if (selectionModel.m_bShow && toolsModel.IsSelection())
         return TRUE;
-    if (ToolBase::s_pointSP != 0)
-        return TRUE;
     return imageModel.CanUndo();
 }
 
@@ -702,8 +700,6 @@ BOOL CMainWindow::CanRedo() const
 {
     if (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow))
         return FALSE; // There is no "WM_REDO" in EDIT control
-    if (ToolBase::s_pointSP != 0)
-        return TRUE;
     return imageModel.CanRedo();
 }
 
@@ -802,29 +798,11 @@ LRESULT CMainWindow::OnGetMinMaxInfo(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BO
 
 LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
 {
-    HWND hwndCapture;
     switch (wParam)
     {
         case VK_ESCAPE:
-            hwndCapture = GetCapture();
-            if (hwndCapture)
-            {
-                if (canvasWindow.m_hWnd == hwndCapture ||
-                    fullscreenWindow.m_hWnd == hwndCapture)
-                {
-                    ::SendMessageW(hwndCapture, nMsg, wParam, lParam);
-                }
-            }
-            else if (selectionModel.m_bShow)
-            {
-                selectionModel.HideSelection();
-            }
-            else
-            {
-                canvasWindow.cancelDrawing();
-            }
+            canvasWindow.PostMessage(nMsg, wParam, lParam);
             break;
-
         case VK_LEFT:
             selectionModel.moveSelection(-1, 0);
             break;
@@ -932,7 +910,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                 GlobalFree(pd.hDevNames);
             break;
         case IDM_FILESEND:
-            canvasWindow.finishDrawing();
+            canvasWindow.OnEndDraw(FALSE);
             if (!OpenMailer(m_hWnd, g_szFileName))
             {
                 ShowError(IDS_CANTSENDMAIL);
@@ -963,7 +941,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                 textEditWindow.PostMessage(WM_UNDO, 0, 0);
                 break;
             }
-            canvasWindow.finishDrawing();
+            canvasWindow.OnEndDraw(FALSE);
             imageModel.Undo();
             break;
         case IDM_EDITREDO:
@@ -972,7 +950,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                 // There is no "WM_REDO" in EDIT control
                 break;
             }
-            canvasWindow.finishDrawing();
+            canvasWindow.OnEndDraw(FALSE);
             imageModel.Redo();
             break;
         case IDM_EDITCOPY:
@@ -1087,7 +1065,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                     break;
 
                 case TOOL_TEXT:
-                    canvasWindow.cancelDrawing();
+                    canvasWindow.OnEndDraw(TRUE);
                     break;
                 default:
                     break;
diff --git a/base/applications/mspaint/mouse.cpp 
b/base/applications/mspaint/mouse.cpp
index 2dcec274e80..2f97ad9d079 100644
--- a/base/applications/mspaint/mouse.cpp
+++ b/base/applications/mspaint/mouse.cpp
@@ -9,9 +9,11 @@
 #include "precomp.h"
 #include <atlalloc.h>
 
-SIZE_T ToolBase::s_pointSP = 0;
-static SIZE_T s_maxPointSP = 0;
-static CHeapPtr<POINT, CLocalAllocator> s_pointStack;
+static SIZE_T s_pointSP = 0;
+static CHeapPtr<POINT, CLocalAllocator> s_pointsAllocated;
+static POINT s_staticPointStack[512]; // 512 is enough
+static SIZE_T s_maxPointSP = _countof(s_staticPointStack);
+static LPPOINT s_pointStack = s_staticPointStack;
 static POINT g_ptStart, g_ptEnd;
 
 /* FUNCTIONS ********************************************************/
@@ -69,13 +71,50 @@ void getBoundaryOfPtStack(RECT& rcBoundary, INT cPoints, 
const POINT *pPoints)
     rcBoundary = rc;
 }
 
+void ShiftPtStack(INT dx, INT dy)
+{
+    for (SIZE_T i = 0; i < s_pointSP; ++i)
+    {
+        POINT& pt = s_pointStack[i];
+        pt.x += dx;
+        pt.y += dy;
+    }
+}
+
+void BuildMaskFromPtStack()
+{
+    CRect rc;
+    getBoundaryOfPtStack(rc, s_pointSP, s_pointStack);
+
+    ShiftPtStack(-rc.left, -rc.top);
+
+    HDC hdcMem = ::CreateCompatibleDC(NULL);
+    HBITMAP hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
+    HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmMask);
+    ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
+    HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
+    HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
+    ::Polygon(hdcMem, s_pointStack, s_pointSP);
+    ::SelectObject(hdcMem, hbrOld);
+    ::SelectObject(hdcMem, hPenOld);
+    ::SelectObject(hdcMem, hbmOld);
+    ::DeleteDC(hdcMem);
+
+    selectionModel.setMask(rc, hbmMask);
+}
+
 void ToolBase::reset()
 {
+    if (s_pointStack != s_staticPointStack)
+    {
+        s_pointsAllocated.Free();
+        s_pointStack = s_staticPointStack;
+        s_maxPointSP = _countof(s_staticPointStack);
+    }
+
     s_pointSP = 0;
     g_ptEnd = g_ptStart = { -1, -1 };
 
-    selectionModel.ResetPtStack();
-
     if (selectionModel.m_bShow)
     {
         selectionModel.Landing();
@@ -103,16 +142,20 @@ void ToolBase::endEvent()
 
 void ToolBase::pushToPtStack(LONG x, LONG y)
 {
-    if (s_pointSP >= s_maxPointSP)
+    if (s_pointSP + 1 >= s_maxPointSP)
     {
         SIZE_T newMax = s_maxPointSP + 512;
         SIZE_T cbNew = newMax * sizeof(POINT);
-        if (!s_pointStack.ReallocateBytes(cbNew))
+        if (!s_pointsAllocated.ReallocateBytes(cbNew))
         {
             ATLTRACE("%d, %d, %d\n", (INT)s_pointSP, (INT)s_maxPointSP, 
(INT)cbNew);
             return;
         }
 
+        if (s_pointStack == s_staticPointStack)
+            CopyMemory(s_pointsAllocated, s_staticPointStack, s_pointSP * 
sizeof(POINT));
+
+        s_pointStack = s_pointsAllocated;
         s_maxPointSP = newMax;
     }
 
@@ -327,12 +370,13 @@ struct SmoothDrawTool : ToolBase
     }
 };
 
-struct SelectionBaseTool : SmoothDrawTool
+struct SelectionBaseTool : ToolBase
 {
     BOOL m_bLeftButton = FALSE;
     BOOL m_bCtrlKey = FALSE;
     BOOL m_bShiftKey = FALSE;
     BOOL m_bDrawing = FALSE;
+    BOOL m_bNoDrawBack = FALSE;
     HITTEST m_hitSelection = HIT_NONE;
 
     BOOL isRectSelect() const
@@ -342,13 +386,19 @@ struct SelectionBaseTool : SmoothDrawTool
 
     void OnDrawOverlayOnImage(HDC hdc) override
     {
-        if (!selectionModel.IsLanded())
-            selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), 
toolsModel.IsBackgroundTransparent());
+        if (selectionModel.IsLanded() || !selectionModel.m_bShow)
+            return;
+
+        if (!m_bNoDrawBack)
+            selectionModel.DrawBackground(hdc, selectionModel.m_rgbBack);
+
+        selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), 
toolsModel.IsBackgroundTransparent());
     }
 
     void OnDrawOverlayOnCanvas(HDC hdc) override
     {
-        selectionModel.drawFrameOnCanvas(hdc);
+        if (m_bDrawing || selectionModel.m_bShow)
+            selectionModel.drawFrameOnCanvas(hdc);
     }
 
     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) 
override
@@ -374,12 +424,14 @@ struct SelectionBaseTool : SmoothDrawTool
         if (hit != HIT_NONE) // Dragging of selection started?
         {
             if (m_bCtrlKey || m_bShiftKey)
-                imageModel.SelectionClone();
-
+            {
+                imageModel.PushImageForUndo();
+                toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
+            }
             m_hitSelection = hit;
             selectionModel.m_ptHit = pt;
             selectionModel.TakeOff();
-
+            m_bNoDrawBack |= (m_bCtrlKey || m_bShiftKey);
             imageModel.NotifyImageChanged();
             return;
         }
@@ -394,8 +446,8 @@ struct SelectionBaseTool : SmoothDrawTool
         }
         else
         {
-            selectionModel.ResetPtStack();
-            selectionModel.PushToPtStack(pt);
+            s_pointSP = 0;
+            pushToPtStack(pt.x, pt.y);
         }
 
         imageModel.NotifyImageChanged();
@@ -411,18 +463,22 @@ struct SelectionBaseTool : SmoothDrawTool
         if (m_hitSelection != HIT_NONE) // Now dragging selection?
         {
             if (m_bShiftKey)
-                imageModel.SelectionClone(m_bShiftKey);
+                toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
 
             selectionModel.Dragging(m_hitSelection, pt);
             imageModel.NotifyImageChanged();
             return TRUE;
         }
 
+        if (isRectSelect() && ::GetKeyState(VK_SHIFT) < 0)
+            regularize(g_ptStart.x, g_ptStart.y, pt.x, pt.y);
+
         imageModel.Clamp(pt);
+
         if (isRectSelect())
             selectionModel.SetRectFromPoints(g_ptStart, pt);
         else
-            selectionModel.PushToPtStack(pt);
+            pushToPtStack(pt.x, pt.y);
 
         imageModel.NotifyImageChanged();
         return TRUE;
@@ -438,13 +494,20 @@ struct SelectionBaseTool : SmoothDrawTool
 
         if (m_hitSelection != HIT_NONE) // Dragging of selection ended?
         {
+            if (m_bShiftKey)
+                toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
+
             selectionModel.Dragging(m_hitSelection, pt);
             m_hitSelection = HIT_NONE;
             imageModel.NotifyImageChanged();
             return TRUE;
         }
 
+        if (isRectSelect() && ::GetKeyState(VK_SHIFT) < 0)
+            regularize(g_ptStart.x, g_ptStart.y, pt.x, pt.y);
+
         imageModel.Clamp(pt);
+
         if (isRectSelect())
         {
             selectionModel.SetRectFromPoints(g_ptStart, pt);
@@ -452,18 +515,19 @@ struct SelectionBaseTool : SmoothDrawTool
         }
         else
         {
-            if (selectionModel.PtStackSize() > 2)
+            if (s_pointSP > 2)
             {
-                selectionModel.BuildMaskFromPtStack();
+                BuildMaskFromPtStack();
                 selectionModel.m_bShow = TRUE;
             }
             else
             {
-                selectionModel.ResetPtStack();
+                s_pointSP = 0;
                 selectionModel.m_bShow = FALSE;
             }
         }
 
+        m_bNoDrawBack = FALSE;
         imageModel.NotifyImageChanged();
         return TRUE;
     }
@@ -475,6 +539,7 @@ struct SelectionBaseTool : SmoothDrawTool
         else
             selectionModel.Landing();
 
+        m_bDrawing = FALSE;
         m_hitSelection = HIT_NONE;
         ToolBase::OnEndDraw(bCancel);
     }
@@ -488,34 +553,21 @@ struct SelectionBaseTool : SmoothDrawTool
 // TOOL_FREESEL
 struct FreeSelTool : SelectionBaseTool
 {
-    void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
-    {
-        if (m_bShiftKey && !m_bCtrlKey)
-        {
-            // TODO:
-        }
-    }
-
     void OnDrawOverlayOnImage(HDC hdc) override
     {
         SelectionBaseTool::OnDrawOverlayOnImage(hdc);
 
         if (!selectionModel.m_bShow && m_bDrawing)
-            selectionModel.DrawFramePoly(hdc);
+        {
+            /* Draw the freehand selection inverted/xored */
+            Poly(hdc, s_pointStack, s_pointSP, 0, 0, 2, 0, FALSE, TRUE);
+        }
     }
 };
 
 // TOOL_RECTSEL
 struct RectSelTool : SelectionBaseTool
 {
-    void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
-    {
-        if (m_bShiftKey && !m_bCtrlKey)
-        {
-            // TODO:
-        }
-    }
-
     void OnDrawOverlayOnImage(HDC hdc) override
     {
         SelectionBaseTool::OnDrawOverlayOnImage(hdc);
diff --git a/base/applications/mspaint/selectionmodel.cpp 
b/base/applications/mspaint/selectionmodel.cpp
index ee18b521188..2699a8517e9 100644
--- a/base/applications/mspaint/selectionmodel.cpp
+++ b/base/applications/mspaint/selectionmodel.cpp
@@ -15,8 +15,6 @@ SelectionModel selectionModel;
 SelectionModel::SelectionModel()
     : m_hbmColor(NULL)
     , m_hbmMask(NULL)
-    , m_ptStack(NULL)
-    , m_iPtSP(0)
     , m_rgbBack(RGB(255, 255, 255))
     , m_bShow(FALSE)
     , m_bContentChanged(FALSE)
@@ -30,69 +28,6 @@ SelectionModel::~SelectionModel()
 {
     ClearColorImage();
     ClearMaskImage();
-    ResetPtStack();
-}
-
-void SelectionModel::ResetPtStack()
-{
-    if (m_ptStack)
-    {
-        free(m_ptStack);
-        m_ptStack = NULL;
-    }
-    m_iPtSP = 0;
-}
-
-void SelectionModel::PushToPtStack(POINT pt)
-{
-#define GROW_COUNT 256
-    if (m_iPtSP % GROW_COUNT == 0)
-    {
-        INT nNewCount = m_iPtSP + GROW_COUNT;
-        LPPOINT pptNew = (LPPOINT)realloc(m_ptStack, sizeof(POINT) * 
nNewCount);
-        if (pptNew == NULL)
-            return;
-        m_ptStack = pptNew;
-    }
-    m_ptStack[m_iPtSP] = pt;
-    m_iPtSP++;
-#undef GROW_COUNT
-}
-
-void SelectionModel::ShiftPtStack(INT dx, INT dy)
-{
-    for (INT i = 0; i < m_iPtSP; ++i)
-    {
-        POINT& pt = m_ptStack[i];
-        pt.x += dx;
-        pt.y += dy;
-    }
-}
-
-void SelectionModel::BuildMaskFromPtStack()
-{
-    CRect rc;
-    getBoundaryOfPtStack(rc, m_iPtSP, m_ptStack);
-
-    m_rc = m_rcOld = rc;
-
-    ClearMaskImage();
-
-    ShiftPtStack(-m_rcOld.left, -m_rcOld.top);
-
-    HDC hdcMem = ::CreateCompatibleDC(NULL);
-    m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
-    HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
-    ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
-    HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
-    HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
-    ::Polygon(hdcMem, m_ptStack, m_iPtSP);
-    ::SelectObject(hdcMem, hbrOld);
-    ::SelectObject(hdcMem, hPenOld);
-    ::SelectObject(hdcMem, hbmOld);
-    ::DeleteDC(hdcMem);
-
-    ShiftPtStack(+m_rcOld.left, +m_rcOld.top);
 }
 
 void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
@@ -100,11 +35,11 @@ void SelectionModel::DrawBackgroundPoly(HDC hDCImage, 
COLORREF crBg)
     if (m_rcOld.IsRectEmpty())
         return;
 
-    HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN));
-    HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg));
-    ::Polygon(hDCImage, m_ptStack, m_iPtSP);
-    ::DeleteObject(::SelectObject(hDCImage, hbrOld));
-    ::SelectObject(hDCImage, hPenOld);
+    HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::GetStockObject(DC_BRUSH));
+    ::SetDCBrushColor(hDCImage, crBg);
+    ::MaskBlt(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.Width(), 
m_rcOld.Height(),
+              hDCImage, m_rcOld.left, m_rcOld.top, m_hbmMask, 0, 0, 
MAKEROP4(PATCOPY, SRCCOPY));
+    ::SelectObject(hDCImage, hbrOld);
 }
 
 void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
@@ -115,12 +50,12 @@ void SelectionModel::DrawBackgroundRect(HDC hDCImage, 
COLORREF crBg)
     Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, 
crBg, crBg, 0, 1);
 }
 
-void SelectionModel::DrawBackground(HDC hDCImage)
+void SelectionModel::DrawBackground(HDC hDCImage, COLORREF crBg)
 {
     if (toolsModel.GetActiveTool() == TOOL_FREESEL)
-        DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
+        DrawBackgroundPoly(hDCImage, crBg);
     else
-        DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
+        DrawBackgroundRect(hDCImage, crBg);
 }
 
 void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL 
bBgTransparent)
@@ -143,6 +78,15 @@ void SelectionModel::DrawSelection(HDC hDCImage, COLORREF 
crBg, BOOL bBgTranspar
     DeleteDC(hMemDC);
 }
 
+void SelectionModel::setMask(const CRect& rc, HBITMAP hbmMask)
+{
+    if (m_hbmMask)
+        ::DeleteObject(m_hbmMask);
+
+    m_hbmMask = hbmMask;
+    m_rc = m_rcOld = rc;
+}
+
 HBITMAP SelectionModel::GetSelectionContents()
 {
     if (m_hbmColor)
@@ -178,17 +122,6 @@ BOOL SelectionModel::TakeOff()
     // Save the selection area
     m_rcOld = m_rc;
 
-    if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
-    {
-        imageModel.PushImageForUndo();
-        selectionModel.DrawBackgroundRect(imageModel.GetDC(), 
selectionModel.m_rgbBack);
-    }
-    else if (toolsModel.GetActiveTool() == TOOL_FREESEL)
-    {
-        imageModel.PushImageForUndo();
-        selectionModel.DrawBackgroundPoly(imageModel.GetDC(), 
selectionModel.m_rgbBack);
-    }
-
     imageModel.NotifyImageChanged();
     return TRUE;
 }
@@ -201,12 +134,12 @@ void SelectionModel::Landing()
         return;
     }
 
-    m_bShow = FALSE;
-
     if (m_bContentChanged ||
         (!m_rc.EqualRect(m_rcOld) && !m_rc.IsRectEmpty() && 
!m_rcOld.IsRectEmpty()))
     {
-        imageModel.PushImageForUndo();
+        CRect rc;
+        rc.UnionRect(m_rc, m_rcOld);
+        imageModel.PushImageForUndo(rc);
 
         canvasWindow.m_drawing = FALSE;
         toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
@@ -397,17 +330,6 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int 
nStretchPercentY, int
     NotifyContentChanged();
 }
 
-int SelectionModel::PtStackSize() const
-{
-    return m_iPtSP;
-}
-
-void SelectionModel::DrawFramePoly(HDC hDCImage)
-{
-    /* draw the freehand selection inverted/xored */
-    Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE);
-}
-
 void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
 {
     m_rc = CRect(ptFrom, ptTo);
@@ -491,7 +413,7 @@ void SelectionModel::DeleteSelection()
 
     TakeOff();
     imageModel.PushImageForUndo();
-    DrawBackground(imageModel.GetDC());
+    DrawBackground(imageModel.GetDC(), paletteModel.GetBgColor());
 
     HideSelection();
 }
diff --git a/base/applications/mspaint/selectionmodel.h 
b/base/applications/mspaint/selectionmodel.h
index e83786191ff..d9007d6df00 100644
--- a/base/applications/mspaint/selectionmodel.h
+++ b/base/applications/mspaint/selectionmodel.h
@@ -13,8 +13,6 @@ class SelectionModel
 private:
     HBITMAP m_hbmColor;
     HBITMAP m_hbmMask;
-    POINT *m_ptStack;
-    int m_iPtSP;
 
 public:
     COLORREF m_rgbBack;
@@ -27,11 +25,8 @@ public:
     SelectionModel();
     ~SelectionModel();
 
-    void ResetPtStack();
-    void PushToPtStack(POINT pt);
-    int PtStackSize() const;
     void SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo);
-    void BuildMaskFromPtStack();
+    void setMask(const CRect& rc, HBITMAP hbmMask);
 
     BOOL TakeOff();
     void Landing();
@@ -43,8 +38,7 @@ public:
     void moveSelection(INT xDelta, INT yDelta);
 
     HBITMAP GetSelectionContents();
-    void DrawFramePoly(HDC hDCImage);
-    void DrawBackground(HDC hDCImage);
+    void DrawBackground(HDC hDCImage, COLORREF crBg);
     void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
     void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
     void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = 
FALSE);
diff --git a/base/applications/mspaint/toolsmodel.cpp 
b/base/applications/mspaint/toolsmodel.cpp
index c19a1152c24..f789fbf9d6a 100644
--- a/base/applications/mspaint/toolsmodel.cpp
+++ b/base/applications/mspaint/toolsmodel.cpp
@@ -209,6 +209,9 @@ SIZE ToolsModel::GetToolSize() const
     {
         case TOOL_FREESEL:
         case TOOL_RECTSEL:
+            size.cx = selectionModel.m_rc.Width();
+            size.cy = selectionModel.m_rc.Height();
+            break;
         case TOOL_COLOR:
         case TOOL_ZOOM:
         case TOOL_TEXT:
diff --git a/base/applications/mspaint/toolsmodel.h 
b/base/applications/mspaint/toolsmodel.h
index 668c7820bb3..2cd2e68d235 100644
--- a/base/applications/mspaint/toolsmodel.h
+++ b/base/applications/mspaint/toolsmodel.h
@@ -42,7 +42,6 @@ struct ToolBase
 {
     HDC m_hdc;
     COLORREF m_fg, m_bg;
-    static SIZE_T s_pointSP;
 
     ToolBase() : m_hdc(NULL) { }
     virtual ~ToolBase() { }

Reply via email to