[MSPAINT] Implement canvas rotation (#4360)

- Add Rotate90DegreeBlt function to dib.cpp.
- Implement ImageModel::RotateNTimes90Degrees and SelectionModel::RotateNTimes90Degrees.
- Improve ToolsModel::SetBackgroundTransparent.
- Extend and improve SelectionModel::InsertFromHBITMAP.
CORE-16634
This commit is contained in:
Katayama Hirofumi MZ 2022-02-14 12:08:34 +09:00 committed by GitHub
parent 6eccbe27ec
commit 2d90919047
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 7 deletions

View file

@ -208,3 +208,38 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile)
return hBitmap; return hBitmap;
} }
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight)
{
HBITMAP hbm2 = CreateDIBWithProperties(cy, cx);
if (!hbm2)
return NULL;
HDC hDC2 = CreateCompatibleDC(NULL);
HGDIOBJ hbm2Old = SelectObject(hDC2, hbm2);
if (bRight)
{
for (INT y = 0; y < cy; ++y)
{
for (INT x = 0; x < cx; ++x)
{
COLORREF rgb = GetPixel(hDC1, x, y);
SetPixelV(hDC2, cy - (y + 1), x, rgb);
}
}
}
else
{
for (INT y = 0; y < cy; ++y)
{
for (INT x = 0; x < cx; ++x)
{
COLORREF rgb = GetPixel(hDC1, x, y);
SetPixelV(hDC2, y, cx - (x + 1), rgb);
}
}
}
SelectObject(hDC2, hbm2Old);
DeleteDC(hDC2);
return hbm2;
}

View file

@ -27,3 +27,5 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile);
void ShowFileLoadError(LPCTSTR name); void ShowFileLoadError(LPCTSTR name);
HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile); HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile);
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight);

View file

@ -245,11 +245,25 @@ void ImageModel::FlipVertically()
void ImageModel::RotateNTimes90Degrees(int iN) void ImageModel::RotateNTimes90Degrees(int iN)
{ {
if (iN == 2) switch (iN)
{ {
case 1:
case 3:
DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
hBms[(currInd + 1) % HISTORYSIZE] = Rotate90DegreeBlt(hDrawingDC, GetWidth(), GetHeight(), iN == 1);
currInd = (currInd + 1) % HISTORYSIZE;
if (undoSteps < HISTORYSIZE - 1)
undoSteps++;
redoSteps = 0;
SelectObject(hDrawingDC, hBms[currInd]);
imageSaved = FALSE;
NotifyDimensionsChanged();
break;
case 2:
CopyPrevious(); CopyPrevious();
StretchBlt(hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), GetDC(), StretchBlt(hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), GetDC(),
0, 0, GetWidth(), GetHeight(), SRCCOPY); 0, 0, GetWidth(), GetHeight(), SRCCOPY);
break;
} }
NotifyImageChanged(); NotifyImageChanged();
} }

View file

@ -344,7 +344,8 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument
if (fontsDialog.IsWindow() && IsDialogMessage(fontsDialog, &messages)) if (fontsDialog.IsWindow() && IsDialogMessage(fontsDialog, &messages))
continue; continue;
TranslateAccelerator(hwnd, haccel, &messages); if (TranslateAccelerator(hwnd, haccel, &messages))
continue;
/* Translate virtual-key messages into character messages */ /* Translate virtual-key messages into character messages */
TranslateMessage(&messages); TranslateMessage(&messages);

View file

@ -266,6 +266,7 @@ LRESULT CSelectionWindow::OnToolsModelSettingsChanged(UINT nMsg, WPARAM wParam,
LRESULT CSelectionWindow::OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CSelectionWindow::OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
ForceRefreshSelectionContents();
return 0; return 0;
} }

View file

@ -165,7 +165,7 @@ void SelectionModel::ScaleContentsToFit()
DeleteDC(hTempDC); DeleteDC(hTempDC);
} }
void SelectionModel::InsertFromHBITMAP(HBITMAP hBm) void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
{ {
HDC hTempDC; HDC hTempDC;
HBITMAP hTempMask; HBITMAP hTempMask;
@ -174,14 +174,15 @@ void SelectionModel::InsertFromHBITMAP(HBITMAP hBm)
DeleteObject(SelectObject(m_hDC, m_hBm)); DeleteObject(SelectObject(m_hDC, m_hBm));
SetRectEmpty(&m_rcSrc); SetRectEmpty(&m_rcSrc);
m_rcDest.left = m_rcDest.top = 0; m_rcDest.left = x;
m_rcDest.top = y;
m_rcDest.right = m_rcDest.left + GetDIBWidth(m_hBm); m_rcDest.right = m_rcDest.left + GetDIBWidth(m_hBm);
m_rcDest.bottom = m_rcDest.top + GetDIBHeight(m_hBm); m_rcDest.bottom = m_rcDest.top + GetDIBHeight(m_hBm);
hTempDC = CreateCompatibleDC(m_hDC); hTempDC = CreateCompatibleDC(m_hDC);
hTempMask = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL); hTempMask = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
SelectObject(hTempDC, hTempMask); SelectObject(hTempDC, hTempMask);
Rect(hTempDC, m_rcDest.left, m_rcDest.top, m_rcDest.right, m_rcDest.bottom, 0x00ffffff, 0x00ffffff, 1, 1); Rect(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 0x00ffffff, 0x00ffffff, 1, 1);
DeleteObject(m_hMask); DeleteObject(m_hMask);
m_hMask = hTempMask; m_hMask = hTempMask;
DeleteDC(hTempDC); DeleteDC(hTempDC);
@ -211,14 +212,29 @@ void SelectionModel::FlipVertically()
void SelectionModel::RotateNTimes90Degrees(int iN) void SelectionModel::RotateNTimes90Degrees(int iN)
{ {
if (iN == 2) HBITMAP hbm;
switch (iN)
{ {
case 1:
case 3:
imageModel.DeleteSelection();
imageModel.CopyPrevious();
SelectObject(m_hDC, m_hBm);
hbm = Rotate90DegreeBlt(m_hDC, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), iN == 1);
InsertFromHBITMAP(hbm, m_rcDest.left, m_rcDest.top);
DeleteObject(hbm);
selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
selectionWindow.ForceRefreshSelectionContents();
placeSelWin();
break;
case 2:
SelectObject(m_hDC, m_hMask); SelectObject(m_hDC, m_hMask);
StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC, StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY); 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
SelectObject(m_hDC, m_hBm); SelectObject(m_hDC, m_hBm);
StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC, StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY); 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
break;
} }
NotifyRefreshNeeded(); NotifyRefreshNeeded();
} }

View file

@ -50,7 +50,7 @@ public:
void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE); void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
void DrawSelectionStretched(HDC hDCImage); void DrawSelectionStretched(HDC hDCImage);
void ScaleContentsToFit(); void ScaleContentsToFit();
void InsertFromHBITMAP(HBITMAP hBm); void InsertFromHBITMAP(HBITMAP hBm, INT x = 0, INT y = 0);
void FlipHorizontally(); void FlipHorizontally();
void FlipVertically(); void FlipVertically();
void RotateNTimes90Degrees(int iN); void RotateNTimes90Degrees(int iN);

View file

@ -141,6 +141,8 @@ void ToolsModel::SetBackgroundTransparent(BOOL bTransparent)
{ {
m_transpBg = bTransparent; m_transpBg = bTransparent;
NotifyToolSettingsChanged(); NotifyToolSettingsChanged();
if (selectionWindow.IsWindow())
selectionWindow.ForceRefreshSelectionContents();
} }
int ToolsModel::GetZoom() const int ToolsModel::GetZoom() const

View file

@ -664,6 +664,10 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
imageModel.FlipVertically(); imageModel.FlipVertically();
break; break;
case 3: /* rotate 90 degrees */ case 3: /* rotate 90 degrees */
if (::IsWindowVisible(selectionWindow))
selectionModel.RotateNTimes90Degrees(1);
else
imageModel.RotateNTimes90Degrees(1);
break; break;
case 4: /* rotate 180 degrees */ case 4: /* rotate 180 degrees */
if (::IsWindowVisible(selectionWindow)) if (::IsWindowVisible(selectionWindow))
@ -672,6 +676,10 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
imageModel.RotateNTimes90Degrees(2); imageModel.RotateNTimes90Degrees(2);
break; break;
case 5: /* rotate 270 degrees */ case 5: /* rotate 270 degrees */
if (::IsWindowVisible(selectionWindow))
selectionModel.RotateNTimes90Degrees(3);
else
imageModel.RotateNTimes90Degrees(3);
break; break;
} }
break; break;