https://git.reactos.org/?p=reactos.git;a=commitdiff;h=389d04650f1dd19cac8e5…
commit 389d04650f1dd19cac8e5587030cb8922500d318
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Sep 26 22:47:23 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Sep 26 22:47:23 2023 +0900
[MSPAINT] Restrict drawing direction on Shift key (#5726)
- While holding down the Shift key, drawing lines with the
pen/brush is limited to either of 8 directions (horizontal/vertical/diagonal).
- s/abs/labs/
CORE-19094
---
base/applications/mspaint/common.h | 5 +-
base/applications/mspaint/dib.cpp | 5 -
base/applications/mspaint/drawing.cpp | 6 +-
base/applications/mspaint/mouse.cpp | 215 ++++++++++++++++++++++++-------
base/applications/mspaint/precomp.h | 2 +
base/applications/mspaint/toolsmodel.cpp | 17 ++-
base/applications/mspaint/toolsmodel.h | 4 +-
7 files changed, 189 insertions(+), 65 deletions(-)
diff --git a/base/applications/mspaint/common.h b/base/applications/mspaint/common.h
index ee103d74911..d2e862b0114 100644
--- a/base/applications/mspaint/common.h
+++ b/base/applications/mspaint/common.h
@@ -45,6 +45,7 @@ enum HITTEST // hit
BOOL zoomTo(int newZoom, int mouseX, int mouseY);
BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1);
-void updateStartAndLast(LONG x, LONG y);
-void updateLast(LONG x, LONG y);
BOOL OpenMailer(HWND hWnd, LPCWSTR pszPathName);
+
+#define DEG2RAD(degree) (((degree) * M_PI) / 180)
+#define RAD2DEG(radian) ((LONG)(((radian) * 180) / M_PI))
diff --git a/base/applications/mspaint/dib.cpp b/base/applications/mspaint/dib.cpp
index ee899c74e98..cd069c9ef6f 100644
--- a/base/applications/mspaint/dib.cpp
+++ b/base/applications/mspaint/dib.cpp
@@ -6,7 +6,6 @@
*/
#include "precomp.h"
-#include <math.h>
INT g_fileSize = 0;
float g_xDpi = 96;
@@ -339,10 +338,6 @@ HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL
bMono)
return hbm2;
}
-#ifndef M_PI
- #define M_PI 3.14159265
-#endif
-
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono)
{
CWaitCursor waitCursor;
diff --git a/base/applications/mspaint/drawing.cpp
b/base/applications/mspaint/drawing.cpp
index dc5e8c433c0..638e78396e2 100644
--- a/base/applications/mspaint/drawing.cpp
+++ b/base/applications/mspaint/drawing.cpp
@@ -115,7 +115,7 @@ Fill(HDC hdc, LONG x, LONG y, COLORREF color)
void
Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG radius)
{
- LONG b = max(1, max(abs(x2 - x1), abs(y2 - y1)));
+ LONG b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
HBRUSH hbr = ::CreateSolidBrush(color);
for (LONG a = 0; a <= b; a++)
@@ -132,7 +132,7 @@ Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color,
LONG radius)
void
Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LONG
radius)
{
- LONG b = max(1, max(abs(x2 - x1), abs(y2 - y1)));
+ LONG b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
for (LONG a = 0; a <= b; a++)
{
@@ -169,7 +169,7 @@ Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color,
LONG style)
HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, color));
HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(color));
LONG a, b;
- b = max(1, max(abs(x2 - x1), abs(y2 - y1)));
+ b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
switch (style)
{
case 0:
diff --git a/base/applications/mspaint/mouse.cpp b/base/applications/mspaint/mouse.cpp
index f896ccd84f3..d8e3585c252 100644
--- a/base/applications/mspaint/mouse.cpp
+++ b/base/applications/mspaint/mouse.cpp
@@ -18,28 +18,28 @@ POINT ToolBase::s_pointStack[256] = { { 0 } };
void
regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
{
- if (abs(x1 - x0) >= abs(y1 - y0))
- y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
+ if (labs(x1 - x0) >= labs(y1 - y0))
+ y1 = y0 + (y1 > y0 ? labs(x1 - x0) : -labs(x1 - x0));
else
- x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
+ x1 = x0 + (x1 > x0 ? labs(y1 - y0) : -labs(y1 - y0));
}
void
roundTo8Directions(LONG x0, LONG y0, LONG& x1, LONG& y1)
{
- if (abs(x1 - x0) >= abs(y1 - y0))
+ if (labs(x1 - x0) >= labs(y1 - y0))
{
- if (abs(y1 - y0) * 5 < abs(x1 - x0) * 2)
+ if (labs(y1 - y0) * 5 < labs(x1 - x0) * 2)
y1 = y0;
else
- y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
+ y1 = y0 + (y1 > y0 ? labs(x1 - x0) : -labs(x1 - x0));
}
else
{
- if (abs(x1 - x0) * 5 < abs(y1 - y0) * 2)
+ if (labs(x1 - x0) * 5 < labs(y1 - y0) * 2)
x1 = x0;
else
- x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
+ x1 = x0 + (x1 > x0 ? labs(y1 - y0) : -labs(y1 - y0));
}
}
@@ -50,18 +50,6 @@ BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1)
return (abs(x1 - x0) <= cxThreshold) && (abs(y1 - y0) <= cyThreshold);
}
-void updateStartAndLast(LONG x, LONG y)
-{
- g_ptStart.x = g_ptEnd.x = x;
- g_ptStart.y = g_ptEnd.y = y;
-}
-
-void updateLast(LONG x, LONG y)
-{
- g_ptEnd.x = x;
- g_ptEnd.y = y;
-}
-
void ToolBase::reset()
{
s_pointSP = 0;
@@ -153,7 +141,7 @@ struct FreeSelTool : ToolBase
m_bLeftButton = bLeftButton;
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
if (bLeftButton)
{
@@ -162,9 +150,10 @@ struct FreeSelTool : ToolBase
selectionModel.PushToPtStack(pt);
imageModel.NotifyImageChanged();
}
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
if (bLeftButton)
{
@@ -186,6 +175,7 @@ struct FreeSelTool : ToolBase
canvasWindow.ClientToScreen(&pt);
mainWindow.TrackPopupMenu(pt, 0);
}
+ return TRUE;
}
void OnFinishDraw() override
@@ -246,7 +236,7 @@ struct RectSelTool : ToolBase
m_bLeftButton = bLeftButton;
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
if (bLeftButton)
{
@@ -255,9 +245,10 @@ struct RectSelTool : ToolBase
selectionModel.SetRectFromPoints(g_ptStart, pt);
imageModel.NotifyImageChanged();
}
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
POINT pt = { x, y };
if (bLeftButton)
@@ -272,6 +263,7 @@ struct RectSelTool : ToolBase
canvasWindow.ClientToScreen(&pt);
mainWindow.TrackPopupMenu(pt, 0);
}
+ return TRUE;
}
void OnFinishDraw() override
@@ -305,26 +297,22 @@ struct TwoPointDrawTool : ToolBase
{
m_bLeftButton = bLeftButton;
m_bDrawing = TRUE;
- g_ptStart.x = g_ptEnd.x = x;
- g_ptStart.y = g_ptEnd.y = y;
imageModel.NotifyImageChanged();
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
- g_ptEnd.x = x;
- g_ptEnd.y = y;
imageModel.NotifyImageChanged();
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
- g_ptEnd.x = x;
- g_ptEnd.y = y;
imageModel.PushImageForUndo();
OnDrawOverlayOnImage(m_hdc);
m_bDrawing = FALSE;
imageModel.NotifyImageChanged();
+ return TRUE;
}
void OnFinishDraw() override
@@ -340,8 +328,101 @@ struct TwoPointDrawTool : ToolBase
}
};
+typedef enum DIRECTION
+{
+ NO_DIRECTION = -1,
+ DIRECTION_HORIZONTAL,
+ DIRECTION_VERTICAL,
+ DIRECTION_DIAGONAL_RIGHT_DOWN,
+ DIRECTION_DIAGONAL_RIGHT_UP,
+} DIRECTION;
+
+#define THRESHOULD_DEG 15
+
+static DIRECTION
+GetDirection(LONG x0, LONG y0, LONG x1, LONG y1)
+{
+ LONG dx = x1 - x0, dy = y1 - y0;
+
+ if (labs(dx) <= 8 && labs(dy) <= 8)
+ return NO_DIRECTION;
+
+ double radian = atan2((double)dy, (double)dx);
+ if (radian < DEG2RAD(-180 + THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_HORIZONTAL: %ld\n", RAD2DEG(radian));
+ return DIRECTION_HORIZONTAL;
+ }
+ if (radian < DEG2RAD(-90 - THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_DIAGONAL_RIGHT_DOWN: %ld\n", RAD2DEG(radian));
+ return DIRECTION_DIAGONAL_RIGHT_DOWN;
+ }
+ if (radian < DEG2RAD(-90 + THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_VERTICAL: %ld\n", RAD2DEG(radian));
+ return DIRECTION_VERTICAL;
+ }
+ if (radian < DEG2RAD(-THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_DIAGONAL_RIGHT_UP: %ld\n", RAD2DEG(radian));
+ return DIRECTION_DIAGONAL_RIGHT_UP;
+ }
+ if (radian < DEG2RAD(+THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_HORIZONTAL: %ld\n", RAD2DEG(radian));
+ return DIRECTION_HORIZONTAL;
+ }
+ if (radian < DEG2RAD(+90 - THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_DIAGONAL_RIGHT_DOWN: %ld\n", RAD2DEG(radian));
+ return DIRECTION_DIAGONAL_RIGHT_DOWN;
+ }
+ if (radian < DEG2RAD(+90 + THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_VERTICAL: %ld\n", RAD2DEG(radian));
+ return DIRECTION_VERTICAL;
+ }
+ if (radian < DEG2RAD(+180 - THRESHOULD_DEG))
+ {
+ ATLTRACE("DIRECTION_DIAGONAL_RIGHT_UP: %ld\n", RAD2DEG(radian));
+ return DIRECTION_DIAGONAL_RIGHT_UP;
+ }
+ ATLTRACE("DIRECTION_HORIZONTAL: %ld\n", RAD2DEG(radian));
+ return DIRECTION_HORIZONTAL;
+}
+
+static void
+RestrictDrawDirection(DIRECTION dir, LONG x0, LONG y0, LONG& x1, LONG& y1)
+{
+ switch (dir)
+ {
+ case NO_DIRECTION:
+ default:
+ return;
+
+ case DIRECTION_HORIZONTAL:
+ y1 = y0;
+ break;
+
+ case DIRECTION_VERTICAL:
+ x1 = x0;
+ break;
+
+ case DIRECTION_DIAGONAL_RIGHT_DOWN:
+ y1 = y0 + (x1 - x0);
+ break;
+
+ case DIRECTION_DIAGONAL_RIGHT_UP:
+ x1 = x0 - (y1 - y0);
+ break;
+ }
+}
+
struct SmoothDrawTool : ToolBase
{
+ DIRECTION m_direction = NO_DIRECTION;
+
SmoothDrawTool(TOOLTYPE type) : ToolBase(type)
{
}
@@ -350,22 +431,51 @@ struct SmoothDrawTool : ToolBase
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
{
+ m_direction = NO_DIRECTION;
imageModel.PushImageForUndo();
- g_ptStart.x = g_ptEnd.x = x;
- g_ptStart.y = g_ptEnd.y = y;
imageModel.NotifyImageChanged();
}
- void 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_direction == NO_DIRECTION)
+ {
+ m_direction = GetDirection(g_ptStart.x, g_ptStart.y, x, y);
+ if (m_direction == NO_DIRECTION)
+ return FALSE;
+ }
+
+ RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y);
+ }
+ else
+ {
+ if (m_direction != NO_DIRECTION)
+ {
+ m_direction = NO_DIRECTION;
+ draw(bLeftButton, x, y);
+ g_ptStart.x = g_ptEnd.x = x;
+ g_ptStart.y = g_ptEnd.y = y;
+ return TRUE;
+ }
+ }
+
draw(bLeftButton, x, y);
imageModel.NotifyImageChanged();
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
+ if (m_direction != NO_DIRECTION)
+ {
+ RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y);
+ }
+
draw(bLeftButton, x, y);
OnFinishDraw();
+ return TRUE;
}
void OnFinishDraw() override
@@ -375,7 +485,8 @@ struct SmoothDrawTool : ToolBase
void OnCancelDraw() override
{
- OnButtonUp(FALSE, 0, 0);
+ LONG x = 0, y = 0;
+ OnButtonUp(FALSE, x, y);
imageModel.Undo(TRUE);
ToolBase::OnCancelDraw();
}
@@ -435,15 +546,17 @@ struct ColorTool : ToolBase
paletteModel.SetBgColor(rgbColor);
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
fetchColor(bLeftButton, x, y);
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
fetchColor(bLeftButton, x, y);
toolsModel.SetActiveTool(toolsModel.GetOldActiveTool());
+ return TRUE;
}
};
@@ -550,9 +663,10 @@ struct TextTool : ToolBase
UpdatePoint(x, y);
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
UpdatePoint(x, y);
+ return TRUE;
}
void draw(HDC hdc)
@@ -578,7 +692,7 @@ struct TextTool : ToolBase
selectionModel.HideSelection();
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
POINT pt = { x, y };
imageModel.Clamp(pt);
@@ -595,7 +709,7 @@ struct TextTool : ToolBase
if (::IsRectEmpty(&selectionModel.m_rc))
{
quit();
- return;
+ return TRUE;
}
}
@@ -630,6 +744,7 @@ struct TextTool : ToolBase
textEditWindow.ValidateEditRect(&rc);
textEditWindow.ShowWindow(SW_SHOWNOACTIVATE);
textEditWindow.SetFocus();
+ return TRUE;
}
void OnFinishDraw() override
@@ -720,23 +835,25 @@ struct BezierTool : ToolBase
imageModel.NotifyImageChanged();
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
s_pointStack[s_pointSP].x = x;
s_pointStack[s_pointSP].y = y;
imageModel.NotifyImageChanged();
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
s_pointStack[s_pointSP].x = x;
s_pointStack[s_pointSP].y = y;
if (s_pointSP >= 3)
{
OnFinishDraw();
- return;
+ return TRUE;
}
imageModel.NotifyImageChanged();
+ return TRUE;
}
void OnCancelDraw() override
@@ -822,7 +939,7 @@ struct ShapeTool : ToolBase
imageModel.NotifyImageChanged();
}
- void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
{
if ((s_pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
roundTo8Directions(s_pointStack[s_pointSP - 1].x, s_pointStack[s_pointSP -
1].y, x, y);
@@ -831,9 +948,10 @@ struct ShapeTool : ToolBase
s_pointStack[s_pointSP].y = y;
imageModel.NotifyImageChanged();
+ return TRUE;
}
- void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
{
if ((s_pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
roundTo8Directions(s_pointStack[s_pointSP - 1].x, s_pointStack[s_pointSP -
1].y, x, y);
@@ -842,7 +960,7 @@ struct ShapeTool : ToolBase
if (nearlyEqualPoints(x, y, s_pointStack[0].x, s_pointStack[0].y))
{
OnFinishDraw();
- return;
+ return TRUE;
}
else
{
@@ -855,6 +973,7 @@ struct ShapeTool : ToolBase
s_pointSP--;
imageModel.NotifyImageChanged();
+ return TRUE;
}
void OnCancelDraw() override
diff --git a/base/applications/mspaint/precomp.h b/base/applications/mspaint/precomp.h
index 51413a4ed6c..09775b0cb72 100644
--- a/base/applications/mspaint/precomp.h
+++ b/base/applications/mspaint/precomp.h
@@ -21,6 +21,8 @@
#include <commdlg.h>
#include <commctrl.h>
#include <stdlib.h>
+#define _USE_MATH_DEFINES /* for M_PI */
+#include <math.h>
#include <shellapi.h>
#include <htmlhelp.h>
#include "atlimagedx.h"
diff --git a/base/applications/mspaint/toolsmodel.cpp
b/base/applications/mspaint/toolsmodel.cpp
index b9a5ac2e4b6..b787e6d591e 100644
--- a/base/applications/mspaint/toolsmodel.cpp
+++ b/base/applications/mspaint/toolsmodel.cpp
@@ -189,24 +189,31 @@ void ToolsModel::NotifyZoomChanged()
void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
{
m_pToolObject->beginEvent();
- updateStartAndLast(x, y);
m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
+ g_ptStart.x = g_ptEnd.x = x;
+ g_ptStart.y = g_ptEnd.y = y;
m_pToolObject->endEvent();
}
void ToolsModel::OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
{
m_pToolObject->beginEvent();
- m_pToolObject->OnMouseMove(bLeftButton, x, y);
- updateLast(x, y);
+ if (m_pToolObject->OnMouseMove(bLeftButton, x, y))
+ {
+ g_ptEnd.x = x;
+ g_ptEnd.y = y;
+ }
m_pToolObject->endEvent();
}
void ToolsModel::OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
{
m_pToolObject->beginEvent();
- m_pToolObject->OnButtonUp(bLeftButton, x, y);
- updateLast(x, y);
+ if (m_pToolObject->OnButtonUp(bLeftButton, x, y))
+ {
+ g_ptEnd.x = x;
+ g_ptEnd.y = y;
+ }
m_pToolObject->endEvent();
}
diff --git a/base/applications/mspaint/toolsmodel.h
b/base/applications/mspaint/toolsmodel.h
index 33335c07ffd..09f48672a01 100644
--- a/base/applications/mspaint/toolsmodel.h
+++ b/base/applications/mspaint/toolsmodel.h
@@ -42,8 +42,8 @@ struct ToolBase
virtual ~ToolBase() { }
virtual void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) { }
- virtual void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) { }
- virtual void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) { }
+ virtual BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) { return TRUE;
}
+ virtual BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) { return TRUE; }
virtual void OnCancelDraw();
virtual void OnFinishDraw();