https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dfd06ee8fc53882a6ef3d…
commit dfd06ee8fc53882a6ef3d7a126aff809cea811f7
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Feb 14 16:18:18 2022 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Feb 14 16:18:18 2022 +0900
[MSPAINT] Implement skew (#4362)
- Add SkewDIB helper function in dib.cpp.
- Implement Stretch and Skew feature by SelectionModel::StretchSkew and
ImageModel::StretchSkew.
- Move ColorKeyedMaskBlt function.
CORE-16634
---
base/applications/mspaint/dib.cpp | 56 ++++++++++++++++++++++++++++
base/applications/mspaint/dib.h | 2 +
base/applications/mspaint/drawing.cpp | 33 ++++++++++++++++
base/applications/mspaint/drawing.h | 5 +++
base/applications/mspaint/history.cpp | 16 +++++++-
base/applications/mspaint/selection.cpp | 33 ----------------
base/applications/mspaint/selectionmodel.cpp | 46 +++++++++++++++++++++--
base/applications/mspaint/selectionmodel.h | 1 +
base/applications/mspaint/winproc.cpp | 12 +++++-
9 files changed, 165 insertions(+), 39 deletions(-)
diff --git a/base/applications/mspaint/dib.cpp b/base/applications/mspaint/dib.cpp
index 711071752ad..01c23fa84bf 100644
--- a/base/applications/mspaint/dib.cpp
+++ b/base/applications/mspaint/dib.cpp
@@ -9,6 +9,7 @@
/* INCLUDES *********************************************************/
#include "precomp.h"
+#include <math.h>
/* FUNCTIONS ********************************************************/
@@ -243,3 +244,58 @@ HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight)
DeleteDC(hDC2);
return hbm2;
}
+
+#ifndef M_PI
+ #define M_PI 3.14159265
+#endif
+
+HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical)
+{
+ if (nDegree == 0)
+ return CopyDIBImage(hbm);
+
+ const double eTan = tan(abs(nDegree) * M_PI / 180);
+
+ BITMAP bm;
+ GetObjectW(hbm, sizeof(bm), &bm);
+ INT cx = bm.bmWidth, cy = bm.bmHeight, dx = 0, dy = 0;
+ if (bVertical)
+ dy = INT(cx * eTan);
+ else
+ dx = INT(cy * eTan);
+
+ if (dx == 0 && dy == 0)
+ return CopyDIBImage(hbm);
+
+ HBITMAP hbmNew = CreateColorDIB(cx + dx, cy + dy, RGB(255, 255, 255));
+ if (!hbmNew)
+ return NULL;
+
+ HDC hDC2 = CreateCompatibleDC(NULL);
+ HGDIOBJ hbm2Old = SelectObject(hDC2, hbmNew);
+ if (bVertical)
+ {
+ for (INT x = 0; x < cx; ++x)
+ {
+ INT delta = INT(x * eTan);
+ if (nDegree > 0)
+ BitBlt(hDC2, x, (dy - delta), 1, cy, hDC1, x, 0, SRCCOPY);
+ else
+ BitBlt(hDC2, x, delta, 1, cy, hDC1, x, 0, SRCCOPY);
+ }
+ }
+ else
+ {
+ for (INT y = 0; y < cy; ++y)
+ {
+ INT delta = INT(y * eTan);
+ if (nDegree > 0)
+ BitBlt(hDC2, (dx - delta), y, cx, 1, hDC1, 0, y, SRCCOPY);
+ else
+ BitBlt(hDC2, delta, y, cx, 1, hDC1, 0, y, SRCCOPY);
+ }
+ }
+ SelectObject(hDC2, hbm2Old);
+ DeleteDC(hDC2);
+ return hbmNew;
+}
diff --git a/base/applications/mspaint/dib.h b/base/applications/mspaint/dib.h
index b045be15a50..e0f8d14f19a 100644
--- a/base/applications/mspaint/dib.h
+++ b/base/applications/mspaint/dib.h
@@ -29,3 +29,5 @@ void ShowFileLoadError(LPCTSTR name);
HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile);
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight);
+
+HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical);
diff --git a/base/applications/mspaint/drawing.cpp
b/base/applications/mspaint/drawing.cpp
index 059559252b9..490ff9a0a62 100644
--- a/base/applications/mspaint/drawing.cpp
+++ b/base/applications/mspaint/drawing.cpp
@@ -307,3 +307,36 @@ Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg,
COLORREF bg, LPCT
RestoreDC(hdc, iSaveDC); // Restore
}
+
+BOOL
+ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
+ HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int
yMask,
+ DWORD dwRop, COLORREF keyColor)
+{
+ HDC hTempDC;
+ HDC hTempDC2;
+ HBITMAP hTempBm;
+ HBRUSH hTempBrush;
+ HBITMAP hTempMask;
+
+ hTempDC = CreateCompatibleDC(hdcSrc);
+ hTempDC2 = CreateCompatibleDC(hdcSrc);
+ hTempBm = CreateCompatibleBitmap(hTempDC, nWidth, nHeight);
+ SelectObject(hTempDC, hTempBm);
+ hTempBrush = CreateSolidBrush(keyColor);
+ SelectObject(hTempDC, hTempBrush);
+ BitBlt(hTempDC, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
+ PatBlt(hTempDC, 0, 0, nWidth, nHeight, PATINVERT);
+ hTempMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
+ SelectObject(hTempDC2, hTempMask);
+ BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, 0, 0, SRCCOPY);
+ SelectObject(hTempDC, hbmMask);
+ BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, xMask, yMask, SRCAND);
+ MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hTempMask,
xMask, yMask, dwRop);
+ DeleteDC(hTempDC);
+ DeleteDC(hTempDC2);
+ DeleteObject(hTempBm);
+ DeleteObject(hTempBrush);
+ DeleteObject(hTempMask);
+ return TRUE;
+}
diff --git a/base/applications/mspaint/drawing.h b/base/applications/mspaint/drawing.h
index 017b71f6ddb..26178a83395 100644
--- a/base/applications/mspaint/drawing.h
+++ b/base/applications/mspaint/drawing.h
@@ -35,3 +35,8 @@ void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);
void SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF
system_selection_color);
void Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR
lpchText, HFONT font, LONG style);
+
+extern BOOL
+ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
+ HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int
yMask,
+ DWORD dwRop, COLORREF keyColor);
diff --git a/base/applications/mspaint/history.cpp
b/base/applications/mspaint/history.cpp
index d771fd37225..f0a3691ed5e 100644
--- a/base/applications/mspaint/history.cpp
+++ b/base/applications/mspaint/history.cpp
@@ -192,7 +192,21 @@ void ImageModel::StretchSkew(int nStretchPercentX, int
nStretchPercentY, int nSk
int oldHeight = GetHeight();
INT newWidth = oldWidth * nStretchPercentX / 100;
INT newHeight = oldHeight * nStretchPercentY / 100;
- Insert(CopyDIBImage(hBms[currInd], newWidth, newHeight));
+ if (oldWidth != newWidth || oldHeight != newHeight)
+ {
+ HBITMAP hbm0 = CopyDIBImage(hBms[currInd], newWidth, newHeight);
+ Insert(hbm0);
+ }
+ if (nSkewDegX)
+ {
+ HBITMAP hbm1 = SkewDIB(hDrawingDC, hBms[currInd], nSkewDegX, FALSE);
+ Insert(hbm1);
+ }
+ if (nSkewDegY)
+ {
+ HBITMAP hbm2 = SkewDIB(hDrawingDC, hBms[currInd], nSkewDegY, TRUE);
+ Insert(hbm2);
+ }
if (GetWidth() != oldWidth || GetHeight() != oldHeight)
NotifyDimensionsChanged();
NotifyImageChanged();
diff --git a/base/applications/mspaint/selection.cpp
b/base/applications/mspaint/selection.cpp
index 992b946a28a..3a87a21f19d 100644
--- a/base/applications/mspaint/selection.cpp
+++ b/base/applications/mspaint/selection.cpp
@@ -21,39 +21,6 @@ const LPCTSTR CSelectionWindow::m_lpszCursorLUT[9] = { /* action to
mouse cursor
IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE
};
-BOOL
-ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
- HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int
yMask,
- DWORD dwRop, COLORREF keyColor)
-{
- HDC hTempDC;
- HDC hTempDC2;
- HBITMAP hTempBm;
- HBRUSH hTempBrush;
- HBITMAP hTempMask;
-
- hTempDC = CreateCompatibleDC(hdcSrc);
- hTempDC2 = CreateCompatibleDC(hdcSrc);
- hTempBm = CreateCompatibleBitmap(hTempDC, nWidth, nHeight);
- SelectObject(hTempDC, hTempBm);
- hTempBrush = CreateSolidBrush(keyColor);
- SelectObject(hTempDC, hTempBrush);
- BitBlt(hTempDC, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
- PatBlt(hTempDC, 0, 0, nWidth, nHeight, PATINVERT);
- hTempMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
- SelectObject(hTempDC2, hTempMask);
- BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, 0, 0, SRCCOPY);
- SelectObject(hTempDC, hbmMask);
- BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, xMask, yMask, SRCAND);
- MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hTempMask,
xMask, yMask, dwRop);
- DeleteDC(hTempDC);
- DeleteDC(hTempDC2);
- DeleteObject(hTempBm);
- DeleteObject(hTempBrush);
- DeleteObject(hTempMask);
- return TRUE;
-}
-
void CSelectionWindow::ForceRefreshSelectionContents()
{
if (::IsWindowVisible(selectionWindow))
diff --git a/base/applications/mspaint/selectionmodel.cpp
b/base/applications/mspaint/selectionmodel.cpp
index c65ae21ac84..3cd41e1f64f 100644
--- a/base/applications/mspaint/selectionmodel.cpp
+++ b/base/applications/mspaint/selectionmodel.cpp
@@ -124,9 +124,6 @@ void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
Rect(hDCImage, m_rcSrc.left, m_rcSrc.top, m_rcSrc.right, m_rcSrc.bottom, crBg, crBg,
0, 1);
}
-extern BOOL
-ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC
hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask, DWORD dwRop, COLORREF
keyColor);
-
void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
{
if (!bBgTransparent)
@@ -239,6 +236,49 @@ void SelectionModel::RotateNTimes90Degrees(int iN)
NotifyRefreshNeeded();
}
+void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int
nSkewDegX, int nSkewDegY)
+{
+ if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX
== 0 && nSkewDegY == 0)
+ return;
+
+ imageModel.DeleteSelection();
+ imageModel.CopyPrevious();
+
+ INT oldWidth = RECT_WIDTH(m_rcDest);
+ INT oldHeight = RECT_HEIGHT(m_rcDest);
+ INT newWidth = oldWidth * nStretchPercentX / 100;
+ INT newHeight = oldHeight * nStretchPercentY / 100;
+
+ if (oldWidth != newWidth || oldHeight != newHeight)
+ {
+ SelectObject(m_hDC, m_hBm);
+ HBITMAP hbm0 = CopyDIBImage(m_hBm, newWidth, newHeight);
+ InsertFromHBITMAP(hbm0, m_rcDest.left, m_rcDest.top);
+ DeleteObject(hbm0);
+ }
+
+ if (nSkewDegX)
+ {
+ SelectObject(m_hDC, m_hBm);
+ HBITMAP hbm1 = SkewDIB(m_hDC, m_hBm, nSkewDegX, FALSE);
+ InsertFromHBITMAP(hbm1, m_rcDest.left, m_rcDest.top);
+ DeleteObject(hbm1);
+ }
+
+ if (nSkewDegY)
+ {
+ SelectObject(m_hDC, m_hBm);
+ HBITMAP hbm2 = SkewDIB(m_hDC, m_hBm, nSkewDegY, TRUE);
+ InsertFromHBITMAP(hbm2, m_rcDest.left, m_rcDest.top);
+ DeleteObject(hbm2);
+ }
+
+ selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
+ selectionWindow.ForceRefreshSelectionContents();
+ placeSelWin();
+ NotifyRefreshNeeded();
+}
+
HBITMAP SelectionModel::GetBitmap() const
{
return m_hBm;
diff --git a/base/applications/mspaint/selectionmodel.h
b/base/applications/mspaint/selectionmodel.h
index b3a6982dffe..fbb208fed4b 100644
--- a/base/applications/mspaint/selectionmodel.h
+++ b/base/applications/mspaint/selectionmodel.h
@@ -54,6 +54,7 @@ public:
void FlipHorizontally();
void FlipVertically();
void RotateNTimes90Degrees(int iN);
+ void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX = 0, int
nSkewDegY = 0);
HBITMAP GetBitmap() const;
int PtStackSize() const;
void DrawFramePoly(HDC hDCImage);
diff --git a/base/applications/mspaint/winproc.cpp
b/base/applications/mspaint/winproc.cpp
index 3bc14f6ae72..74e27a67661 100644
--- a/base/applications/mspaint/winproc.cpp
+++ b/base/applications/mspaint/winproc.cpp
@@ -695,8 +695,16 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM
lParam, BOOL& bH
{
if (stretchSkewDialog.DoModal(mainWindow.m_hWnd))
{
- imageModel.StretchSkew(stretchSkewDialog.percentage.x,
stretchSkewDialog.percentage.y,
- stretchSkewDialog.angle.x,
stretchSkewDialog.angle.y);
+ if (::IsWindowVisible(selectionWindow))
+ {
+ selectionModel.StretchSkew(stretchSkewDialog.percentage.x,
stretchSkewDialog.percentage.y,
+ stretchSkewDialog.angle.x,
stretchSkewDialog.angle.y);
+ }
+ else
+ {
+ imageModel.StretchSkew(stretchSkewDialog.percentage.x,
stretchSkewDialog.percentage.y,
+ stretchSkewDialog.angle.x,
stretchSkewDialog.angle.y);
+ }
}
break;
}