mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[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:
parent
6eccbe27ec
commit
2d90919047
9 changed files with 86 additions and 7 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue