[MSPAINT] Larger/smaller brush nib on Ctrl+Plus/Minus (#5739)

- Introduce the concept of "brush width" to the
  tools model.
- Enable changing the brush width by Ctrl+Plus/Minus
  key combination in TOOL_BRUSH.
- Re-define brush styles.
CORE-19094
This commit is contained in:
Katayama Hirofumi MZ 2023-09-28 21:30:34 +09:00 committed by GitHub
parent c84b5007d0
commit 8a4787b384
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 132 additions and 76 deletions

View file

@ -165,73 +165,66 @@ Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r)
}
void
Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style)
Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style, INT thickness)
{
HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, color));
HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(color));
LONG a, b;
b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
switch (style)
if (thickness <= 1)
{
case 0:
for(a = 0; a <= b; a++)
Ellipse(hdc, (x1 * (b - a) + x2 * a) / b - 3, (y1 * (b - a) + y2 * a) / b - 3,
(x1 * (b - a) + x2 * a) / b + 4, (y1 * (b - a) + y2 * a) / b + 4);
break;
case 1:
for(a = 0; a <= b; a++)
Ellipse(hdc,
(x1 * (b - a) + x2 * a) / b - 2,
(y1 * (b - a) + y2 * a) / b - 2,
(x1 * (b - a) + x2 * a) / b + 2,
(y1 * (b - a) + y2 * a) / b + 2);
break;
case 2:
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2);
::SetPixelV(hdc, x2, y2, color);
break;
case 3:
for(a = 0; a <= b; a++)
Rectangle(hdc,
(x1 * (b - a) + x2 * a) / b - 4,
(y1 * (b - a) + y2 * a) / b - 4,
(x1 * (b - a) + x2 * a) / b + 4,
(y1 * (b - a) + y2 * a) / b + 4);
break;
case 4:
for(a = 0; a <= b; a++)
Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 2, (y1 * (b - a) + y2 * a) / b - 2,
(x1 * (b - a) + x2 * a) / b + 3, (y1 * (b - a) + y2 * a) / b + 3);
break;
case 5:
for(a = 0; a <= b; a++)
Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 1, (y1 * (b - a) + y2 * a) / b - 1,
(x1 * (b - a) + x2 * a) / b + 1, (y1 * (b - a) + y2 * a) / b + 1);
break;
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
Line(hdc, x1, y1, x2, y2, color, thickness);
}
else
{
LONG a, b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
switch ((BrushStyle)style)
{
POINT offsTop[] = {{3, -3}, {2, -2}, {0, 0},
{-4, -4}, {-2, -2}, {-1, 0}};
POINT offsBtm[] = {{-3, 3}, {-2, 2}, {-1, 1},
{3, 3}, {2, 2}, {0, 1}};
LONG idx = style - 6;
POINT pts[4];
pts[0].x = x1 + offsTop[idx].x;
pts[0].y = y1 + offsTop[idx].y;
pts[1].x = x1 + offsBtm[idx].x;
pts[1].y = y1 + offsBtm[idx].y;
pts[2].x = x2 + offsBtm[idx].x;
pts[2].y = y2 + offsBtm[idx].y;
pts[3].x = x2 + offsTop[idx].x;
pts[3].y = y2 + offsTop[idx].y;
Polygon(hdc, pts, 4);
break;
case BrushStyleRound:
for (a = 0; a <= b; a++)
{
Ellipse(hdc,
(x1 * (b - a) + x2 * a) / b - (thickness / 2),
(y1 * (b - a) + y2 * a) / b - (thickness / 2),
(x1 * (b - a) + x2 * a) / b + (thickness / 2),
(y1 * (b - a) + y2 * a) / b + (thickness / 2));
}
break;
case BrushStyleSquare:
for (a = 0; a <= b; a++)
{
Rectangle(hdc,
(x1 * (b - a) + x2 * a) / b - (thickness / 2),
(y1 * (b - a) + y2 * a) / b - (thickness / 2),
(x1 * (b - a) + x2 * a) / b + (thickness / 2),
(y1 * (b - a) + y2 * a) / b + (thickness / 2));
}
break;
case BrushStyleForeSlash:
case BrushStyleBackSlash:
{
POINT offsetTop, offsetBottom;
if ((BrushStyle)style == BrushStyleForeSlash)
{
offsetTop = { (thickness - 1) / 2, -(thickness - 1) / 2 };
offsetBottom = { -thickness / 2, thickness / 2 };
}
else
{
offsetTop = { -thickness / 2, -thickness / 2 };
offsetBottom = { (thickness - 1) / 2, (thickness - 1) / 2 };
}
POINT points[4] =
{
{ x1 + offsetTop.x, y1 + offsetTop.y },
{ x1 + offsetBottom.x, y1 + offsetBottom.y },
{ x2 + offsetBottom.x, y2 + offsetBottom.y },
{ x2 + offsetTop.x, y2 + offsetTop.y },
};
Polygon(hdc, points, _countof(points));
break;
}
}
}
DeleteObject(SelectObject(hdc, oldBrush));

View file

@ -27,7 +27,7 @@ void Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF
void Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r);
void Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style);
void Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style, INT thickness);
void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);

View file

@ -609,12 +609,13 @@ struct BrushTool : SmoothDrawTool
void draw(BOOL bLeftButton, LONG x, LONG y) override
{
COLORREF rgb = bLeftButton ? m_fg : m_bg;
Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle());
Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle(),
toolsModel.GetBrushWidth());
}
void OnSpecialTweak(BOOL bMinus) override
{
// TODO:
toolsModel.MakeBrushThickerOrThinner(bMinus);
}
};

View file

@ -112,23 +112,43 @@ static inline INT getBrushRects(RECT rects[12], LPCRECT prc, LPPOINT ppt = NULL)
return getSplitRects(rects, 3, 4, prc, ppt);
}
struct BrushStyleAndWidth
{
BrushStyle style;
INT width;
};
static const BrushStyleAndWidth c_BrushPresets[] =
{
{ BrushStyleRound, 7 }, { BrushStyleRound, 4 }, { BrushStyleRound, 1 },
{ BrushStyleSquare, 8 }, { BrushStyleSquare, 5 }, { BrushStyleSquare, 2 },
{ BrushStyleForeSlash, 8 }, { BrushStyleForeSlash, 5 }, { BrushStyleForeSlash, 2 },
{ BrushStyleBackSlash, 8 }, { BrushStyleBackSlash, 5 }, { BrushStyleBackSlash, 2 },
};
VOID CToolSettingsWindow::drawBrush(HDC hdc, LPCRECT prc)
{
RECT rects[12];
getBrushRects(rects, prc);
::FillRect(hdc, &rects[toolsModel.GetBrushStyle()], (HBRUSH)(COLOR_HIGHLIGHT + 1));
for (INT i = 0; i < 12; i++)
{
RECT rcItem = rects[i];
INT x = (rcItem.left + rcItem.right) / 2, y = (rcItem.top + rcItem.bottom) / 2;
INT iColor;
if (i == toolsModel.GetBrushStyle())
const BrushStyleAndWidth& data = c_BrushPresets[i];
if (data.width == toolsModel.GetBrushWidth() && data.style == toolsModel.GetBrushStyle())
{
iColor = COLOR_HIGHLIGHTTEXT;
::FillRect(hdc, &rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1));
}
else
{
iColor = COLOR_WINDOWTEXT;
Brush(hdc, x, y, x, y, ::GetSysColor(iColor), i);
}
Brush(hdc, x, y, x, y, ::GetSysColor(iColor), data.style, data.width);
}
}
@ -383,7 +403,11 @@ LRESULT CToolSettingsWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lPar
case TOOL_BRUSH:
iItem = getBrushRects(rects, &rect1, &pt);
if (iItem != -1)
toolsModel.SetBrushStyle(iItem);
{
const BrushStyleAndWidth& data = c_BrushPresets[iItem];
toolsModel.SetBrushStyle(data.style);
toolsModel.SetBrushWidth(data.width);
}
break;
case TOOL_AIRBRUSH:
iItem = getAirBrushRects(rects, &rect1, &pt);

View file

@ -14,8 +14,9 @@ ToolsModel toolsModel;
ToolsModel::ToolsModel()
{
m_lineWidth = m_penWidth = 1;
m_brushWidth = 4;
m_shapeStyle = 0;
m_brushStyle = 0;
m_brushStyle = BrushStyleRound;
m_oldActiveTool = m_activeTool = TOOL_PEN;
m_airBrushWidth = 5;
m_rubberRadius = 4;
@ -68,6 +69,18 @@ void ToolsModel::SetPenWidth(INT nPenWidth)
imageModel.NotifyImageChanged();
}
INT ToolsModel::GetBrushWidth() const
{
return m_brushWidth;
}
void ToolsModel::SetBrushWidth(INT nBrushWidth)
{
m_brushWidth = nBrushWidth;
NotifyToolSettingsChanged();
imageModel.NotifyImageChanged();
}
void ToolsModel::MakeLineThickerOrThinner(BOOL bThinner)
{
INT thickness = GetLineWidth();
@ -80,6 +93,12 @@ void ToolsModel::MakePenThickerOrThinner(BOOL bThinner)
SetPenWidth(bThinner ? max(1, thickness - 1) : (thickness + 1));
}
void ToolsModel::MakeBrushThickerOrThinner(BOOL bThinner)
{
INT thickness = GetBrushWidth();
SetBrushWidth(bThinner ? max(1, thickness - 1) : (thickness + 1));
}
int ToolsModel::GetShapeStyle() const
{
return m_shapeStyle;
@ -91,12 +110,12 @@ void ToolsModel::SetShapeStyle(int nShapeStyle)
NotifyToolSettingsChanged();
}
int ToolsModel::GetBrushStyle() const
BrushStyle ToolsModel::GetBrushStyle() const
{
return m_brushStyle;
}
void ToolsModel::SetBrushStyle(int nBrushStyle)
void ToolsModel::SetBrushStyle(BrushStyle nBrushStyle)
{
m_brushStyle = nBrushStyle;
NotifyToolSettingsChanged();

View file

@ -28,6 +28,14 @@ enum TOOLTYPE
TOOL_MAX = TOOL_RRECT,
};
enum BrushStyle
{
BrushStyleRound,
BrushStyleSquare,
BrushStyleForeSlash,
BrushStyleBackSlash,
};
/* CLASSES **********************************************************/
struct ToolBase
@ -68,8 +76,9 @@ class ToolsModel
private:
int m_lineWidth;
INT m_penWidth;
INT m_brushWidth;
int m_shapeStyle;
int m_brushStyle;
BrushStyle m_brushStyle;
TOOLTYPE m_activeTool;
TOOLTYPE m_oldActiveTool;
int m_airBrushWidth;
@ -97,17 +106,27 @@ public:
int GetShapeStyle() const;
void SetShapeStyle(int nShapeStyle);
int GetBrushStyle() const;
void SetBrushStyle(int nBrushStyle);
INT GetBrushWidth() const;
void SetBrushWidth(INT nBrushWidth);
void MakeBrushThickerOrThinner(BOOL bThinner);
BrushStyle GetBrushStyle() const;
void SetBrushStyle(BrushStyle nBrushStyle);
TOOLTYPE GetActiveTool() const;
TOOLTYPE GetOldActiveTool() const;
void SetActiveTool(TOOLTYPE nActiveTool);
int GetAirBrushWidth() const;
void SetAirBrushWidth(int nAirBrushWidth);
int GetRubberRadius() const;
void SetRubberRadius(int nRubberRadius);
BOOL IsBackgroundTransparent() const;
void SetBackgroundTransparent(BOOL bTransparent);
int GetZoom() const;
void SetZoom(int nZoom);