mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
[MSPAINT] Introduce partial image history, Part 2 (#6005)
Follow-up to #5994. Reduce the lag and the cost of drawing on large image. - Introduce partial image history on SmoothDrawTool and ShapeTool. - We can draw with pen smoothly even when the image is huge (10000x10000). CORE-19237
This commit is contained in:
parent
5b5aaf6687
commit
e579220098
7 changed files with 163 additions and 153 deletions
|
@ -40,18 +40,14 @@ RECT CCanvasWindow::GetBaseRect()
|
|||
|
||||
VOID CCanvasWindow::ImageToCanvas(POINT& pt)
|
||||
{
|
||||
pt.x = Zoomed(pt.x);
|
||||
pt.y = Zoomed(pt.y);
|
||||
Zoomed(pt);
|
||||
pt.x += GRIP_SIZE - GetScrollPos(SB_HORZ);
|
||||
pt.y += GRIP_SIZE - GetScrollPos(SB_VERT);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::ImageToCanvas(RECT& rc)
|
||||
{
|
||||
rc.left = Zoomed(rc.left);
|
||||
rc.top = Zoomed(rc.top);
|
||||
rc.right = Zoomed(rc.right);
|
||||
rc.bottom = Zoomed(rc.bottom);
|
||||
Zoomed(rc);
|
||||
::OffsetRect(&rc, GRIP_SIZE - GetScrollPos(SB_HORZ), GRIP_SIZE - GetScrollPos(SB_VERT));
|
||||
}
|
||||
|
||||
|
@ -61,8 +57,7 @@ VOID CCanvasWindow::CanvasToImage(POINT& pt, BOOL bZoomed)
|
|||
pt.y -= GRIP_SIZE - GetScrollPos(SB_VERT);
|
||||
if (bZoomed)
|
||||
return;
|
||||
pt.x = UnZoomed(pt.x);
|
||||
pt.y = UnZoomed(pt.y);
|
||||
UnZoomed(pt);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::CanvasToImage(RECT& rc, BOOL bZoomed)
|
||||
|
@ -70,15 +65,12 @@ VOID CCanvasWindow::CanvasToImage(RECT& rc, BOOL bZoomed)
|
|||
::OffsetRect(&rc, GetScrollPos(SB_HORZ) - GRIP_SIZE, GetScrollPos(SB_VERT) - GRIP_SIZE);
|
||||
if (bZoomed)
|
||||
return;
|
||||
rc.left = UnZoomed(rc.left);
|
||||
rc.top = UnZoomed(rc.top);
|
||||
rc.right = UnZoomed(rc.right);
|
||||
rc.bottom = UnZoomed(rc.bottom);
|
||||
UnZoomed(rc);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::GetImageRect(RECT& rc)
|
||||
{
|
||||
::SetRect(&rc, 0, 0, imageModel.GetWidth(), imageModel.GetHeight());
|
||||
rc = { 0, 0, imageModel.GetWidth(), imageModel.GetHeight() };
|
||||
}
|
||||
|
||||
HITTEST CCanvasWindow::CanvasHitTest(POINT pt)
|
||||
|
@ -689,7 +681,7 @@ LRESULT CCanvasWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
|
|||
{
|
||||
if (wParam == VK_ESCAPE && ::GetCapture() == m_hWnd)
|
||||
{
|
||||
// Cancel dragging
|
||||
cancelDrawing();
|
||||
::ReleaseCapture();
|
||||
m_nMouseDownMsg = 0;
|
||||
m_hitCanvasSizeBox = HIT_NONE;
|
||||
|
|
|
@ -46,6 +46,7 @@ enum HITTEST // hit
|
|||
void ShowOutOfMemory(void);
|
||||
BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1);
|
||||
BOOL OpenMailer(HWND hWnd, LPCWSTR pszPathName);
|
||||
void getBoundaryOfPtStack(RECT& rcBoundary, INT cPoints, const POINT *pPoints);
|
||||
|
||||
#define DEG2RAD(degree) (((degree) * M_PI) / 180)
|
||||
#define RAD2DEG(radian) ((LONG)(((radian) * 180) / M_PI))
|
||||
|
|
|
@ -122,7 +122,6 @@ LRESULT CMiniatureWindow::OnGetMinMaxInfo(UINT nMsg, WPARAM wParam, LPARAM lPara
|
|||
{
|
||||
// Avoid too small
|
||||
LPMINMAXINFO pInfo = (LPMINMAXINFO)lParam;
|
||||
pInfo->ptMinTrackSize.x = 100;
|
||||
pInfo->ptMinTrackSize.y = 75;
|
||||
pInfo->ptMinTrackSize = { 100, 75 };
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
/* INCLUDES *********************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
#include <atlalloc.h>
|
||||
|
||||
INT ToolBase::s_pointSP = 0;
|
||||
POINT ToolBase::s_pointStack[256] = { { 0 } };
|
||||
SIZE_T ToolBase::s_pointSP = 0;
|
||||
static SIZE_T s_maxPointSP = 0;
|
||||
static CHeapPtr<POINT, CLocalAllocator> s_pointStack;
|
||||
static POINT g_ptStart, g_ptEnd;
|
||||
|
||||
/* FUNCTIONS ********************************************************/
|
||||
|
@ -51,11 +53,31 @@ BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1)
|
|||
return (abs(x1 - x0) <= cxThreshold) && (abs(y1 - y0) <= cyThreshold);
|
||||
}
|
||||
|
||||
void getBoundaryOfPtStack(RECT& rcBoundary, INT cPoints, const POINT *pPoints)
|
||||
{
|
||||
POINT ptMin = { MAXLONG, MAXLONG }, ptMax = { (LONG)MINLONG, (LONG)MINLONG };
|
||||
while (cPoints-- > 0)
|
||||
{
|
||||
LONG x = pPoints->x, y = pPoints->y;
|
||||
ptMin = { min(x, ptMin.x), min(y, ptMin.y) };
|
||||
ptMax = { max(x, ptMax.x), max(y, ptMax.y) };
|
||||
++pPoints;
|
||||
}
|
||||
|
||||
ptMax.x += 1;
|
||||
ptMax.y += 1;
|
||||
|
||||
CRect rc(ptMin, ptMax);
|
||||
rcBoundary = rc;
|
||||
}
|
||||
|
||||
void ToolBase::reset()
|
||||
{
|
||||
s_pointSP = 0;
|
||||
g_ptStart.x = g_ptStart.y = g_ptEnd.x = g_ptEnd.y = -1;
|
||||
g_ptEnd = g_ptStart = { -1, -1 };
|
||||
|
||||
selectionModel.ResetPtStack();
|
||||
|
||||
if (selectionModel.m_bShow)
|
||||
{
|
||||
selectionModel.Landing();
|
||||
|
@ -93,6 +115,24 @@ void ToolBase::OnDrawSelectionOnCanvas(HDC hdc)
|
|||
drawSizeBoxes(hdc, &rcSelection, TRUE);
|
||||
}
|
||||
|
||||
void ToolBase::pushToPtStack(LONG x, LONG y)
|
||||
{
|
||||
if (s_pointSP >= s_maxPointSP)
|
||||
{
|
||||
SIZE_T newMax = s_maxPointSP + 512;
|
||||
SIZE_T cbNew = newMax * sizeof(POINT);
|
||||
if (!s_pointStack.ReallocateBytes(cbNew))
|
||||
{
|
||||
ATLTRACE("%d, %d, %d\n", (INT)s_pointSP, (INT)s_maxPointSP, (INT)cbNew);
|
||||
return;
|
||||
}
|
||||
|
||||
s_maxPointSP = newMax;
|
||||
}
|
||||
|
||||
s_pointStack[s_pointSP++] = { x, y };
|
||||
}
|
||||
|
||||
/* TOOLS ********************************************************/
|
||||
|
||||
// TOOL_FREESEL
|
||||
|
@ -410,43 +450,43 @@ struct SmoothDrawTool : ToolBase
|
|||
{
|
||||
DIRECTION m_direction = NO_DIRECTION;
|
||||
BOOL m_bShiftDown = FALSE;
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
|
||||
SmoothDrawTool(TOOLTYPE type) : ToolBase(type)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void draw(BOOL bLeftButton, LONG x, LONG y) = 0;
|
||||
virtual void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) = 0;
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
m_direction = NO_DIRECTION;
|
||||
imageModel.PushImageForUndo();
|
||||
imageModel.NotifyImageChanged();
|
||||
m_bShiftDown = (::GetKeyState(VK_SHIFT) & 0x8000); // Is Shift key pressed?
|
||||
m_bLeftButton = bLeftButton;
|
||||
s_pointSP = 0;
|
||||
pushToPtStack(x, y);
|
||||
pushToPtStack(x, y); // We have to draw the first point
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
|
||||
{
|
||||
if (m_bShiftDown)
|
||||
if (!m_bShiftDown)
|
||||
{
|
||||
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
|
||||
{
|
||||
draw(bLeftButton, x, y);
|
||||
g_ptStart.x = g_ptEnd.x = x;
|
||||
g_ptStart.y = g_ptEnd.y = y;
|
||||
pushToPtStack(x, y);
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
draw(bLeftButton, x, y);
|
||||
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);
|
||||
pushToPtStack(x, y);
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -454,24 +494,30 @@ struct SmoothDrawTool : ToolBase
|
|||
BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
|
||||
{
|
||||
if (m_bShiftDown && m_direction != NO_DIRECTION)
|
||||
{
|
||||
RestrictDrawDirection(m_direction, g_ptStart.x, g_ptStart.y, x, y);
|
||||
}
|
||||
|
||||
draw(bLeftButton, x, y);
|
||||
pushToPtStack(x, y);
|
||||
|
||||
CRect rcPartial;
|
||||
getBoundaryOfPtStack(rcPartial, s_pointSP, s_pointStack);
|
||||
|
||||
SIZE size = toolsModel.GetToolSize();
|
||||
rcPartial.InflateRect((size.cx + 1) / 2, (size.cy + 1) / 2);
|
||||
|
||||
imageModel.PushImageForUndo(rcPartial);
|
||||
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
imageModel.NotifyImageChanged();
|
||||
OnEndDraw(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void OnEndDraw(BOOL bCancel) override
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
if (bCancel)
|
||||
for (SIZE_T i = 1; i < s_pointSP; ++i)
|
||||
{
|
||||
LONG x = 0, y = 0;
|
||||
OnButtonUp(FALSE, x, y);
|
||||
imageModel.Undo(TRUE);
|
||||
OnDraw(hdc, m_bLeftButton, s_pointStack[i - 1], s_pointStack[i]);
|
||||
}
|
||||
ToolBase::OnEndDraw(bCancel);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -482,12 +528,12 @@ struct RubberTool : SmoothDrawTool
|
|||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
|
||||
{
|
||||
if (bLeftButton)
|
||||
Erase(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_bg, toolsModel.GetRubberRadius());
|
||||
Erase(hdc, pt0.x, pt0.y, pt1.x, pt1.y, m_bg, toolsModel.GetRubberRadius());
|
||||
else
|
||||
Replace(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius());
|
||||
Replace(hdc, pt0.x, pt0.y, pt1.x, pt1.y, m_fg, m_bg, toolsModel.GetRubberRadius());
|
||||
}
|
||||
|
||||
void OnSpecialTweak(BOOL bMinus) override
|
||||
|
@ -617,10 +663,10 @@ struct PenTool : SmoothDrawTool
|
|||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
|
||||
{
|
||||
COLORREF rgb = bLeftButton ? m_fg : m_bg;
|
||||
Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetPenWidth());
|
||||
Line(hdc, pt0.x, pt0.y, pt1.x, pt1.y, rgb, toolsModel.GetPenWidth());
|
||||
}
|
||||
|
||||
void OnSpecialTweak(BOOL bMinus) override
|
||||
|
@ -636,10 +682,10 @@ struct BrushTool : SmoothDrawTool
|
|||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
|
||||
{
|
||||
COLORREF rgb = bLeftButton ? m_fg : m_bg;
|
||||
Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle(),
|
||||
Brush(hdc, pt0.x, pt0.y, pt1.x, pt1.y, rgb, toolsModel.GetBrushStyle(),
|
||||
toolsModel.GetBrushWidth());
|
||||
}
|
||||
|
||||
|
@ -652,14 +698,28 @@ struct BrushTool : SmoothDrawTool
|
|||
// TOOL_AIRBRUSH
|
||||
struct AirBrushTool : SmoothDrawTool
|
||||
{
|
||||
DWORD m_dwTick = 0;
|
||||
|
||||
AirBrushTool() : SmoothDrawTool(TOOL_AIRBRUSH)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
m_dwTick = GetTickCount();
|
||||
SmoothDrawTool::OnButtonDown(bLeftButton, x, y, bDoubleClick);
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
srand(m_dwTick);
|
||||
SmoothDrawTool::OnDrawOverlayOnImage(hdc);
|
||||
}
|
||||
|
||||
void OnDraw(HDC hdc, BOOL bLeftButton, POINT pt0, POINT pt1) override
|
||||
{
|
||||
COLORREF rgb = bLeftButton ? m_fg : m_bg;
|
||||
Airbrush(m_hdc, x, y, rgb, toolsModel.GetAirBrushRadius());
|
||||
Airbrush(hdc, pt1.x, pt1.y, rgb, toolsModel.GetAirBrushRadius());
|
||||
}
|
||||
|
||||
void OnSpecialTweak(BOOL bMinus) override
|
||||
|
@ -823,7 +883,6 @@ struct LineTool : TwoPointDrawTool
|
|||
struct BezierTool : ToolBase
|
||||
{
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
BOOL m_bDrawing = FALSE;
|
||||
|
||||
BezierTool() : ToolBase(TOOL_BEZIER)
|
||||
{
|
||||
|
@ -831,20 +890,17 @@ struct BezierTool : ToolBase
|
|||
|
||||
void OnDrawOverlayOnImage(HDC hdc)
|
||||
{
|
||||
if (!m_bDrawing)
|
||||
return;
|
||||
|
||||
COLORREF rgb = (m_bLeftButton ? m_fg : m_bg);
|
||||
switch (s_pointSP)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
Line(hdc, s_pointStack[0].x, s_pointStack[0].y, s_pointStack[1].x, s_pointStack[1].y, rgb,
|
||||
toolsModel.GetLineWidth());
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
Bezier(hdc, s_pointStack[0], s_pointStack[2], s_pointStack[2], s_pointStack[1], rgb, toolsModel.GetLineWidth());
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
Bezier(hdc, s_pointStack[0], s_pointStack[2], s_pointStack[3], s_pointStack[1], rgb, toolsModel.GetLineWidth());
|
||||
break;
|
||||
}
|
||||
|
@ -854,18 +910,14 @@ struct BezierTool : ToolBase
|
|||
{
|
||||
m_bLeftButton = bLeftButton;
|
||||
|
||||
if (!m_bDrawing)
|
||||
if (s_pointSP == 0)
|
||||
{
|
||||
m_bDrawing = TRUE;
|
||||
s_pointStack[s_pointSP].x = s_pointStack[s_pointSP + 1].x = x;
|
||||
s_pointStack[s_pointSP].y = s_pointStack[s_pointSP + 1].y = y;
|
||||
++s_pointSP;
|
||||
pushToPtStack(x, y);
|
||||
pushToPtStack(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
++s_pointSP;
|
||||
s_pointStack[s_pointSP].x = x;
|
||||
s_pointStack[s_pointSP].y = y;
|
||||
s_pointStack[s_pointSP - 1] = { x, y };
|
||||
}
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
|
@ -873,33 +925,32 @@ struct BezierTool : ToolBase
|
|||
|
||||
BOOL OnMouseMove(BOOL bLeftButton, LONG& x, LONG& y) override
|
||||
{
|
||||
s_pointStack[s_pointSP].x = x;
|
||||
s_pointStack[s_pointSP].y = y;
|
||||
if (s_pointSP > 0)
|
||||
s_pointStack[s_pointSP - 1] = { x, y };
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
if (s_pointSP >= 4)
|
||||
{
|
||||
OnEndDraw(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
pushToPtStack(x, y);
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void OnEndDraw(BOOL bCancel) override
|
||||
{
|
||||
if (!bCancel)
|
||||
if (!bCancel && s_pointSP > 1)
|
||||
{
|
||||
// FIXME: I couldn't calculate boundary rectangle from Bezier curve
|
||||
imageModel.PushImageForUndo();
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
}
|
||||
m_bDrawing = FALSE;
|
||||
ToolBase::OnEndDraw(bCancel);
|
||||
}
|
||||
|
||||
|
@ -945,9 +996,9 @@ struct ShapeTool : ToolBase
|
|||
return;
|
||||
|
||||
if (m_bLeftButton)
|
||||
Poly(hdc, s_pointStack, s_pointSP + 1, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
|
||||
Poly(hdc, s_pointStack, s_pointSP, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
|
||||
else
|
||||
Poly(hdc, s_pointStack, s_pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
|
||||
Poly(hdc, s_pointStack, s_pointSP, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
|
@ -958,32 +1009,29 @@ struct ShapeTool : ToolBase
|
|||
if ((s_pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
|
||||
roundTo8Directions(s_pointStack[s_pointSP - 1].x, s_pointStack[s_pointSP - 1].y, x, y);
|
||||
|
||||
s_pointStack[s_pointSP].x = x;
|
||||
s_pointStack[s_pointSP].y = y;
|
||||
pushToPtStack(x, y);
|
||||
|
||||
if (s_pointSP && bDoubleClick)
|
||||
if (s_pointSP > 1 && bDoubleClick)
|
||||
{
|
||||
OnEndDraw(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_pointSP == 0)
|
||||
{
|
||||
s_pointSP++;
|
||||
s_pointStack[s_pointSP].x = x;
|
||||
s_pointStack[s_pointSP].y = y;
|
||||
}
|
||||
if (s_pointSP == 1)
|
||||
pushToPtStack(x, y); // We have to draw the first point
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
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);
|
||||
if (s_pointSP > 1)
|
||||
{
|
||||
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
||||
roundTo8Directions(s_pointStack[s_pointSP - 2].x, s_pointStack[s_pointSP - 2].y, x, y);
|
||||
|
||||
s_pointStack[s_pointSP].x = x;
|
||||
s_pointStack[s_pointSP].y = y;
|
||||
s_pointStack[s_pointSP - 1] = { x, y };
|
||||
}
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
|
@ -991,8 +1039,8 @@ struct ShapeTool : ToolBase
|
|||
|
||||
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);
|
||||
if ((s_pointSP > 1) && (GetAsyncKeyState(VK_SHIFT) < 0))
|
||||
roundTo8Directions(s_pointStack[s_pointSP - 2].x, s_pointStack[s_pointSP - 2].y, x, y);
|
||||
|
||||
m_bClosed = FALSE;
|
||||
if (nearlyEqualPoints(x, y, s_pointStack[0].x, s_pointStack[0].y))
|
||||
|
@ -1000,35 +1048,28 @@ struct ShapeTool : ToolBase
|
|||
OnEndDraw(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_pointSP++;
|
||||
s_pointStack[s_pointSP].x = x;
|
||||
s_pointStack[s_pointSP].y = y;
|
||||
}
|
||||
|
||||
if (s_pointSP == _countof(s_pointStack))
|
||||
s_pointSP--;
|
||||
|
||||
pushToPtStack(x, y);
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void OnEndDraw(BOOL bCancel) override
|
||||
{
|
||||
if (!bCancel)
|
||||
if (!bCancel && s_pointSP > 1)
|
||||
{
|
||||
if (s_pointSP)
|
||||
{
|
||||
--s_pointSP;
|
||||
m_bClosed = TRUE;
|
||||
CRect rcPartial;
|
||||
getBoundaryOfPtStack(rcPartial, s_pointSP, s_pointStack);
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
}
|
||||
m_bClosed = FALSE;
|
||||
s_pointSP = 0;
|
||||
SIZE size = toolsModel.GetToolSize();
|
||||
rcPartial.InflateRect((size.cx + 1) / 2, (size.cy + 1) / 2);
|
||||
|
||||
imageModel.PushImageForUndo(rcPartial);
|
||||
|
||||
m_bClosed = TRUE;
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
}
|
||||
m_bClosed = FALSE;
|
||||
ToolBase::OnEndDraw(bCancel);
|
||||
}
|
||||
|
||||
|
@ -1107,8 +1148,7 @@ ToolBase::createToolObject(TOOLTYPE type)
|
|||
void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
|
||||
{
|
||||
m_pToolObject->beginEvent();
|
||||
g_ptStart.x = g_ptEnd.x = x;
|
||||
g_ptStart.y = g_ptEnd.y = y;
|
||||
g_ptEnd = g_ptStart = { x, y };
|
||||
m_pToolObject->OnButtonDown(bLeftButton, x, y, bDoubleClick);
|
||||
m_pToolObject->endEvent();
|
||||
}
|
||||
|
@ -1117,10 +1157,8 @@ void ToolsModel::OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
|
|||
{
|
||||
m_pToolObject->beginEvent();
|
||||
if (m_pToolObject->OnMouseMove(bLeftButton, x, y))
|
||||
{
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
}
|
||||
g_ptEnd = { x, y };
|
||||
|
||||
m_pToolObject->endEvent();
|
||||
}
|
||||
|
||||
|
@ -1128,10 +1166,8 @@ void ToolsModel::OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
|
|||
{
|
||||
m_pToolObject->beginEvent();
|
||||
if (m_pToolObject->OnButtonUp(bLeftButton, x, y))
|
||||
{
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
}
|
||||
g_ptEnd = { x, y };
|
||||
|
||||
m_pToolObject->endEvent();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ SelectionModel::SelectionModel()
|
|||
{
|
||||
::SetRectEmpty(&m_rc);
|
||||
::SetRectEmpty(&m_rcOld);
|
||||
m_ptHit.x = m_ptHit.y = -1;
|
||||
m_ptHit = { -1, -1 };
|
||||
}
|
||||
|
||||
SelectionModel::~SelectionModel()
|
||||
|
@ -71,17 +71,8 @@ void SelectionModel::ShiftPtStack(INT dx, INT dy)
|
|||
|
||||
void SelectionModel::BuildMaskFromPtStack()
|
||||
{
|
||||
CRect rc = { MAXLONG, MAXLONG, 0, 0 };
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
POINT& pt = m_ptStack[i];
|
||||
rc.left = min(pt.x, rc.left);
|
||||
rc.top = min(pt.y, rc.top);
|
||||
rc.right = max(pt.x, rc.right);
|
||||
rc.bottom = max(pt.y, rc.bottom);
|
||||
}
|
||||
rc.right += 1;
|
||||
rc.bottom += 1;
|
||||
CRect rc;
|
||||
getBoundaryOfPtStack(rc, m_iPtSP, m_ptStack);
|
||||
|
||||
m_rc = m_rcOld = rc;
|
||||
|
||||
|
|
|
@ -43,8 +43,7 @@ struct ToolBase
|
|||
TOOLTYPE m_tool;
|
||||
HDC m_hdc;
|
||||
COLORREF m_fg, m_bg;
|
||||
static INT s_pointSP;
|
||||
static POINT s_pointStack[256];
|
||||
static SIZE_T s_pointSP;
|
||||
|
||||
ToolBase(TOOLTYPE tool) : m_tool(tool), m_hdc(NULL) { }
|
||||
virtual ~ToolBase() { }
|
||||
|
@ -63,6 +62,7 @@ struct ToolBase
|
|||
void beginEvent();
|
||||
void endEvent();
|
||||
void reset();
|
||||
void pushToPtStack(LONG x, LONG y);
|
||||
|
||||
static ToolBase* createToolObject(TOOLTYPE type);
|
||||
|
||||
|
@ -165,28 +165,20 @@ static inline int UnZoomed(int xy)
|
|||
|
||||
static inline void Zoomed(POINT& pt)
|
||||
{
|
||||
pt.x = Zoomed(pt.x);
|
||||
pt.y = Zoomed(pt.y);
|
||||
pt = { Zoomed(pt.x), Zoomed(pt.y) };
|
||||
}
|
||||
|
||||
static inline void Zoomed(RECT& rc)
|
||||
{
|
||||
rc.left = Zoomed(rc.left);
|
||||
rc.top = Zoomed(rc.top);
|
||||
rc.right = Zoomed(rc.right);
|
||||
rc.bottom = Zoomed(rc.bottom);
|
||||
rc = { Zoomed(rc.left), Zoomed(rc.top), Zoomed(rc.right), Zoomed(rc.bottom) };
|
||||
}
|
||||
|
||||
static inline void UnZoomed(POINT& pt)
|
||||
{
|
||||
pt.x = UnZoomed(pt.x);
|
||||
pt.y = UnZoomed(pt.y);
|
||||
pt = { UnZoomed(pt.x), UnZoomed(pt.y) };
|
||||
}
|
||||
|
||||
static inline void UnZoomed(RECT& rc)
|
||||
{
|
||||
rc.left = UnZoomed(rc.left);
|
||||
rc.top = UnZoomed(rc.top);
|
||||
rc.right = UnZoomed(rc.right);
|
||||
rc.bottom = UnZoomed(rc.bottom);
|
||||
rc = { UnZoomed(rc.left), UnZoomed(rc.top), UnZoomed(rc.right), UnZoomed(rc.bottom) };
|
||||
}
|
||||
|
|
|
@ -498,9 +498,8 @@ LRESULT CMainWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHand
|
|||
|
||||
LRESULT CMainWindow::OnGetMinMaxInfo(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
MINMAXINFO *mm = (LPMINMAXINFO) lParam;
|
||||
mm->ptMinTrackSize.x = 330;
|
||||
mm->ptMinTrackSize.y = 360;
|
||||
MINMAXINFO *mm = (MINMAXINFO*)lParam;
|
||||
mm->ptMinTrackSize = { 330, 360 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue