[MSPAINT] Realize Masked Skew

- Add CreateMonoBitmap and CopyMonoImage functions to dib.cpp.
- Add bMono parameter to SkewDIB function.
- Add hbmMask parameter to InsertFromHBITMAP function.
- Add ToolsModel::IsSelection.
CORE-18867
This commit is contained in:
Katayama Hirofumi MZ 2023-06-19 09:56:02 +09:00
parent f6bd638b4d
commit 9afcbea24e
8 changed files with 111 additions and 27 deletions

View file

@ -449,7 +449,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
{
toolsModel.OnMouseMove(TRUE, pt.x, pt.y);
Invalidate(FALSE);
if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || (toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_FREESEL))
if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || toolsModel.IsSelection())
{
CString strSize;
if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))

View file

@ -36,6 +36,26 @@ CreateDIBWithProperties(int width, int height)
return CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
}
HBITMAP
CreateMonoBitmap(int width, int height, BOOL bWhite)
{
HBITMAP hbm = CreateBitmap(width, height, 1, 1, NULL);
if (hbm == NULL)
return NULL;
if (bWhite)
{
HDC hdc = CreateCompatibleDC(NULL);
HGDIOBJ hbmOld = SelectObject(hdc, hbm);
RECT rc = { 0, 0, width, height };
FillRect(hdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH));
SelectObject(hdc, hbmOld);
DeleteDC(hdc);
}
return hbm;
}
HBITMAP
CreateColorDIB(int width, int height, COLORREF rgb)
{
@ -59,6 +79,34 @@ CreateColorDIB(int width, int height, COLORREF rgb)
return ret;
}
HBITMAP CopyMonoImage(HBITMAP hbm, INT cx, INT cy)
{
BITMAP bm;
if (!GetObject(hbm, sizeof(bm), &bm))
return NULL;
if (cx == 0 || cy == 0)
{
cx = bm.bmWidth;
cy = bm.bmHeight;
}
HBITMAP hbmNew = CreateBitmap(cx, cy, 1, 1, NULL);
if (!hbmNew)
return NULL;
HDC hdc1 = CreateCompatibleDC(NULL);
HDC hdc2 = CreateCompatibleDC(NULL);
HGDIOBJ hbm1Old = SelectObject(hdc1, hbm);
HGDIOBJ hbm2Old = SelectObject(hdc2, hbmNew);
StretchBlt(hdc2, 0, 0, cx, cy, hdc1, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
SelectObject(hdc1, hbm1Old);
SelectObject(hdc1, hbm2Old);
DeleteDC(hdc1);
DeleteDC(hdc2);
return hbmNew;
}
HBITMAP CachedBufferDIB(HBITMAP hbm, int minimalWidth, int minimalHeight)
{
if (minimalWidth <= 0)
@ -283,7 +331,7 @@ HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono)
#define M_PI 3.14159265
#endif
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical)
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono)
{
if (nDegree == 0)
return CopyDIBImage(hbm);
@ -301,7 +349,11 @@ HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical)
if (dx == 0 && dy == 0)
return CopyDIBImage(hbm);
HBITMAP hbmNew = CreateColorDIB(cx + dx, cy + dy, RGB(255, 255, 255));
HBITMAP hbmNew;
if (bMono)
hbmNew = CreateMonoBitmap(cx + dx, cy + dy, FALSE);
else
hbmNew = CreateColorDIB(cx + dx, cy + dy, RGB(255, 255, 255));
if (!hbmNew)
return NULL;
@ -329,6 +381,7 @@ HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical)
BitBlt(hDC2, delta, y, cx, 1, hDC1, 0, y, SRCCOPY);
}
}
SelectObject(hDC2, hbm2Old);
DeleteDC(hDC2);
return hbmNew;

View file

@ -9,9 +9,12 @@
#pragma once
HBITMAP CreateDIBWithProperties(int width, int height);
HBITMAP CreateMonoBitmap(int width, int height, BOOL bWhite);
HBITMAP CreateColorDIB(int width, int height, COLORREF rgb);
HBITMAP CachedBufferDIB(HBITMAP hbm, int minimalWidth, int minimalHeight);
HBITMAP CopyMonoImage(HBITMAP hbm, INT cx = 0, INT cy = 0);
static inline HBITMAP CopyDIBImage(HBITMAP hbm, INT cx = 0, INT cy = 0)
{
return (HBITMAP)CopyImage(hbm, IMAGE_BITMAP, cx, cy, LR_COPYRETURNORG | LR_CREATEDIBSECTION);
@ -31,7 +34,7 @@ HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL i
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono);
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical);
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono = FALSE);
float PpcmFromDpi(float dpi);

View file

@ -209,19 +209,27 @@ void SelectionModel::Landing()
HideSelection();
}
void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
void SelectionModel::InsertFromHBITMAP(HBITMAP hbmColor, INT x, INT y, HBITMAP hbmMask)
{
::DeleteObject(m_hbmColor);
m_hbmColor = CopyDIBImage(hBm);
m_hbmColor = CopyDIBImage(hbmColor);
m_rc.left = x;
m_rc.top = y;
m_rc.right = x + GetDIBWidth(hBm);
m_rc.bottom = y + GetDIBHeight(hBm);
m_rc.right = x + GetDIBWidth(hbmColor);
m_rc.bottom = y + GetDIBHeight(hbmColor);
if (hbmMask)
{
::DeleteObject(m_hbmMask);
m_hbmMask = CopyMonoImage(hbmMask);
}
else
{
ClearMask();
}
NotifyContentChanged();
ClearMask();
}
void SelectionModel::FlipHorizontally()
@ -336,29 +344,45 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int
INT newWidth = oldWidth * nStretchPercentX / 100;
INT newHeight = oldHeight * nStretchPercentY / 100;
HBITMAP hbmColor, hbmMask;
HGDIOBJ hbmOld;
if (m_hbmMask == NULL)
m_hbmMask = CreateMonoBitmap(newWidth, newHeight, TRUE);
if (oldWidth != newWidth || oldHeight != newHeight)
{
HBITMAP hbm0 = CopyDIBImage(m_hbmColor, newWidth, newHeight);
InsertFromHBITMAP(hbm0, m_rc.left, m_rc.top);
::DeleteObject(hbm0);
hbmColor = CopyDIBImage(m_hbmColor, newWidth, newHeight);
hbmMask = CopyMonoImage(m_hbmMask, newWidth, newHeight);
InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask);
::DeleteObject(hbmColor);
::DeleteObject(hbmMask);
}
HDC hDC = ::CreateCompatibleDC(NULL);
if (nSkewDegX)
{
::SelectObject(hDC, m_hbmColor);
HBITMAP hbm1 = SkewDIB(hDC, m_hbmColor, nSkewDegX, FALSE);
InsertFromHBITMAP(hbm1, m_rc.left, m_rc.top);
::DeleteObject(hbm1);
hbmOld = ::SelectObject(hDC, m_hbmColor);
hbmColor = SkewDIB(hDC, m_hbmColor, nSkewDegX, FALSE);
::SelectObject(hDC, m_hbmMask);
hbmMask = SkewDIB(hDC, m_hbmMask, nSkewDegX, FALSE, TRUE);
InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask);
::SelectObject(hDC, hbmOld);
::DeleteObject(hbmColor);
::DeleteObject(hbmMask);
}
if (nSkewDegY)
{
::SelectObject(hDC, m_hbmColor);
HBITMAP hbm2 = SkewDIB(hDC, m_hbmColor, nSkewDegY, TRUE);
InsertFromHBITMAP(hbm2, m_rc.left, m_rc.top);
::DeleteObject(hbm2);
hbmOld = ::SelectObject(hDC, m_hbmColor);
hbmColor = SkewDIB(hDC, m_hbmColor, nSkewDegY, TRUE);
::SelectObject(hDC, m_hbmMask);
hbmMask = SkewDIB(hDC, m_hbmColor, nSkewDegY, TRUE, TRUE);
InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask);
::SelectObject(hDC, hbmOld);
::DeleteObject(hbmColor);
::DeleteObject(hbmMask);
}
::DeleteDC(hDC);

View file

@ -47,7 +47,7 @@ public:
void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
void InsertFromHBITMAP(HBITMAP hBm, INT x = 0, INT y = 0);
void InsertFromHBITMAP(HBITMAP hbmColor, INT x = 0, INT y = 0, HBITMAP hbmMask = NULL);
// operation
void FlipHorizontally();

View file

@ -40,6 +40,11 @@ ToolBase *ToolsModel::GetOrCreateTool(TOOLTYPE nTool)
return m_tools[nTool];
}
BOOL ToolsModel::IsSelection() const
{
return (GetActiveTool() == TOOL_RECTSEL || GetActiveTool() == TOOL_FREESEL);
}
int ToolsModel::GetLineWidth() const
{
return m_lineWidth;

View file

@ -82,6 +82,8 @@ private:
public:
ToolsModel();
~ToolsModel();
BOOL IsSelection() const;
int GetLineWidth() const;
void SetLineWidth(int nLineWidth);
int GetShapeStyle() const;

View file

@ -419,9 +419,7 @@ void CMainWindow::ProcessFileMenu(HMENU hPopupMenu)
LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HMENU menu = (HMENU)wParam;
BOOL trueSelection =
(selectionModel.m_bShow &&
((toolsModel.GetActiveTool() == TOOL_FREESEL) || (toolsModel.GetActiveTool() == TOOL_RECTSEL)));
BOOL trueSelection = (selectionModel.m_bShow && toolsModel.IsSelection());
BOOL textShown = (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow));
DWORD dwStart = 0, dwEnd = 0;
if (textShown)
@ -667,8 +665,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
}
if (selectionModel.m_bShow)
{
if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
toolsModel.GetActiveTool() == TOOL_FREESEL)
if (toolsModel.IsSelection())
{
canvasWindow.cancelDrawing();
break;