1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: PAINT for ReactOS
38f1f1c7aSStanislav Motylkov * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4c2c66affSColin Finck * PURPOSE: Keep track of selection parameters, notify listeners
5f5200e6cSStanislav Motylkov * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
68f1f1c7aSStanislav Motylkov * Copyright 2019 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck #include "precomp.h"
10c2c66affSColin Finck
1129e147beSKatayama Hirofumi MZ SelectionModel selectionModel;
1229e147beSKatayama Hirofumi MZ
13c2c66affSColin Finck /* FUNCTIONS ********************************************************/
14c2c66affSColin Finck
SelectionModel()15c2c66affSColin Finck SelectionModel::SelectionModel()
16aac89519SKatayama Hirofumi MZ : m_hbmColor(NULL)
17aac89519SKatayama Hirofumi MZ , m_hbmMask(NULL)
1817bdf554SKatayama Hirofumi MZ , m_rgbBack(RGB(255, 255, 255))
19aac89519SKatayama Hirofumi MZ , m_bShow(FALSE)
207aadc1e1SKatayama Hirofumi MZ , m_bContentChanged(FALSE)
21c2c66affSColin Finck {
221aeebfdaSKatayama Hirofumi MZ m_rc.SetRectEmpty();
231aeebfdaSKatayama Hirofumi MZ m_rcOld.SetRectEmpty();
24e5792200SKatayama Hirofumi MZ m_ptHit = { -1, -1 };
253fa95ab9SKatayama Hirofumi MZ }
26c2c66affSColin Finck
~SelectionModel()273fa95ab9SKatayama Hirofumi MZ SelectionModel::~SelectionModel()
283fa95ab9SKatayama Hirofumi MZ {
29ed9973f8SKatayama Hirofumi MZ ClearColorImage();
30ed9973f8SKatayama Hirofumi MZ ClearMaskImage();
31c2c66affSColin Finck }
32c2c66affSColin Finck
DrawBackgroundPoly(HDC hDCImage,COLORREF crBg)33c2c66affSColin Finck void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
34c2c66affSColin Finck {
351aeebfdaSKatayama Hirofumi MZ if (m_rcOld.IsRectEmpty())
36e8c7e300SKatayama Hirofumi MZ return;
37aac89519SKatayama Hirofumi MZ
38b8598e09SKatayama Hirofumi MZ HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::GetStockObject(DC_BRUSH));
39b8598e09SKatayama Hirofumi MZ ::SetDCBrushColor(hDCImage, crBg);
40b8598e09SKatayama Hirofumi MZ ::MaskBlt(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.Width(), m_rcOld.Height(),
41b8598e09SKatayama Hirofumi MZ hDCImage, m_rcOld.left, m_rcOld.top, m_hbmMask, 0, 0, MAKEROP4(PATCOPY, SRCCOPY));
42b8598e09SKatayama Hirofumi MZ ::SelectObject(hDCImage, hbrOld);
43c2c66affSColin Finck }
44c2c66affSColin Finck
DrawBackgroundRect(HDC hDCImage,COLORREF crBg)45c2c66affSColin Finck void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
46c2c66affSColin Finck {
471aeebfdaSKatayama Hirofumi MZ if (m_rcOld.IsRectEmpty())
48e8c7e300SKatayama Hirofumi MZ return;
49e8c7e300SKatayama Hirofumi MZ
50e8c7e300SKatayama Hirofumi MZ Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1);
51c2c66affSColin Finck }
52c2c66affSColin Finck
DrawBackground(HDC hDCImage,COLORREF crBg)53b8598e09SKatayama Hirofumi MZ void SelectionModel::DrawBackground(HDC hDCImage, COLORREF crBg)
547aadc1e1SKatayama Hirofumi MZ {
557aadc1e1SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_FREESEL)
56b8598e09SKatayama Hirofumi MZ DrawBackgroundPoly(hDCImage, crBg);
577aadc1e1SKatayama Hirofumi MZ else
58b8598e09SKatayama Hirofumi MZ DrawBackgroundRect(hDCImage, crBg);
597aadc1e1SKatayama Hirofumi MZ }
607aadc1e1SKatayama Hirofumi MZ
61*e928b427SKatayama Hirofumi MZ void
DrawSelection(HDC hDCImage,COLORREF crBg,BOOL bBgTransparent,const CRect & rc,HBITMAP hbm)62*e928b427SKatayama Hirofumi MZ SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent, const CRect& rc,
63*e928b427SKatayama Hirofumi MZ HBITMAP hbm)
64c2c66affSColin Finck {
651aeebfdaSKatayama Hirofumi MZ if (rc.IsRectEmpty())
66aac89519SKatayama Hirofumi MZ return;
67aac89519SKatayama Hirofumi MZ
68aac89519SKatayama Hirofumi MZ BITMAP bm;
69*e928b427SKatayama Hirofumi MZ if (!GetObjectW(hbm, sizeof(BITMAP), &bm))
70e8c7e300SKatayama Hirofumi MZ return;
71aac89519SKatayama Hirofumi MZ
72aac89519SKatayama Hirofumi MZ COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
73aac89519SKatayama Hirofumi MZ
74aac89519SKatayama Hirofumi MZ HDC hMemDC = CreateCompatibleDC(hDCImage);
75*e928b427SKatayama Hirofumi MZ HGDIOBJ hbmOld = SelectObject(hMemDC, hbm);
76aac89519SKatayama Hirofumi MZ ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(),
77aac89519SKatayama Hirofumi MZ hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor);
78aac89519SKatayama Hirofumi MZ SelectObject(hMemDC, hbmOld);
79aac89519SKatayama Hirofumi MZ DeleteDC(hMemDC);
80aac89519SKatayama Hirofumi MZ }
81aac89519SKatayama Hirofumi MZ
setMask(const CRect & rc,HBITMAP hbmMask)82b8598e09SKatayama Hirofumi MZ void SelectionModel::setMask(const CRect& rc, HBITMAP hbmMask)
83b8598e09SKatayama Hirofumi MZ {
84b8598e09SKatayama Hirofumi MZ if (m_hbmMask)
85b8598e09SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask);
86b8598e09SKatayama Hirofumi MZ
87b8598e09SKatayama Hirofumi MZ m_hbmMask = hbmMask;
88b8598e09SKatayama Hirofumi MZ m_rc = m_rcOld = rc;
89b8598e09SKatayama Hirofumi MZ }
90b8598e09SKatayama Hirofumi MZ
GetSelectionContents()91d7ece626SKatayama Hirofumi MZ HBITMAP SelectionModel::GetSelectionContents()
92aac89519SKatayama Hirofumi MZ {
93764e5505SKatayama Hirofumi MZ HBITMAP hbmWhole = imageModel.LockBitmap();
94*e928b427SKatayama Hirofumi MZ HBITMAP hbmPart = getSubImage(hbmWhole, (IsLanded() ? m_rc : m_rcOld));
95764e5505SKatayama Hirofumi MZ imageModel.UnlockBitmap(hbmWhole);
96*e928b427SKatayama Hirofumi MZ if (!hbmPart)
97*e928b427SKatayama Hirofumi MZ return NULL;
98*e928b427SKatayama Hirofumi MZ
99*e928b427SKatayama Hirofumi MZ CRect rc = { 0, 0, m_rc.Width(), m_rc.Height() };
100*e928b427SKatayama Hirofumi MZ
101*e928b427SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL);
102*e928b427SKatayama Hirofumi MZ HBITMAP hbmNew = CreateColorDIB(rc.Width(), rc.Height(), paletteModel.GetBgColor());
103*e928b427SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmNew);
104*e928b427SKatayama Hirofumi MZ selectionModel.DrawSelection(hdcMem, paletteModel.GetBgColor(), TRUE, rc, hbmPart);
105*e928b427SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld);
106*e928b427SKatayama Hirofumi MZ ::DeleteDC(hdcMem);
107*e928b427SKatayama Hirofumi MZ
108*e928b427SKatayama Hirofumi MZ ::DeleteObject(hbmPart);
109*e928b427SKatayama Hirofumi MZ return hbmNew;
110aac89519SKatayama Hirofumi MZ }
111aac89519SKatayama Hirofumi MZ
IsLanded() const112e8c7e300SKatayama Hirofumi MZ BOOL SelectionModel::IsLanded() const
113e8c7e300SKatayama Hirofumi MZ {
114e8c7e300SKatayama Hirofumi MZ return !m_hbmColor;
115e8c7e300SKatayama Hirofumi MZ }
116e8c7e300SKatayama Hirofumi MZ
TakeOff()117aac89519SKatayama Hirofumi MZ BOOL SelectionModel::TakeOff()
118aac89519SKatayama Hirofumi MZ {
1191aeebfdaSKatayama Hirofumi MZ if (!IsLanded() || m_rc.IsRectEmpty())
120aac89519SKatayama Hirofumi MZ return FALSE;
121aac89519SKatayama Hirofumi MZ
122ed9973f8SKatayama Hirofumi MZ // The background color is needed for transparency of selection
123e8c7e300SKatayama Hirofumi MZ m_rgbBack = paletteModel.GetBgColor();
124ed9973f8SKatayama Hirofumi MZ
125ed9973f8SKatayama Hirofumi MZ // Get the contents of the selection area
126d7ece626SKatayama Hirofumi MZ ClearColorImage();
127d7ece626SKatayama Hirofumi MZ m_hbmColor = GetSelectionContents();
128aac89519SKatayama Hirofumi MZ
129ed9973f8SKatayama Hirofumi MZ // RectSel doesn't need the mask image
130e8c7e300SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
131ed9973f8SKatayama Hirofumi MZ ClearMaskImage();
132e8c7e300SKatayama Hirofumi MZ
133ed9973f8SKatayama Hirofumi MZ // Save the selection area
134e8c7e300SKatayama Hirofumi MZ m_rcOld = m_rc;
135c2c66affSColin Finck
136bfd42c67SKatayama Hirofumi MZ imageModel.NotifyImageChanged();
137aac89519SKatayama Hirofumi MZ return TRUE;
138c2c66affSColin Finck }
139c2c66affSColin Finck
Landing()140aac89519SKatayama Hirofumi MZ void SelectionModel::Landing()
141c2c66affSColin Finck {
142e8c7e300SKatayama Hirofumi MZ if (IsLanded() && !m_bShow)
143e8c7e300SKatayama Hirofumi MZ {
144e8c7e300SKatayama Hirofumi MZ imageModel.NotifyImageChanged();
145aac89519SKatayama Hirofumi MZ return;
146e8c7e300SKatayama Hirofumi MZ }
147aac89519SKatayama Hirofumi MZ
1487aadc1e1SKatayama Hirofumi MZ if (m_bContentChanged ||
1491aeebfdaSKatayama Hirofumi MZ (!m_rc.EqualRect(m_rcOld) && !m_rc.IsRectEmpty() && !m_rcOld.IsRectEmpty()))
150e8c7e300SKatayama Hirofumi MZ {
151b8598e09SKatayama Hirofumi MZ CRect rc;
152b8598e09SKatayama Hirofumi MZ rc.UnionRect(m_rc, m_rcOld);
153b8598e09SKatayama Hirofumi MZ imageModel.PushImageForUndo(rc);
154e8c7e300SKatayama Hirofumi MZ
155e8c7e300SKatayama Hirofumi MZ canvasWindow.m_drawing = FALSE;
156e8c7e300SKatayama Hirofumi MZ toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
157e8c7e300SKatayama Hirofumi MZ }
158e8c7e300SKatayama Hirofumi MZ
159e8c7e300SKatayama Hirofumi MZ HideSelection();
160c2c66affSColin Finck }
161c2c66affSColin Finck
InsertFromHBITMAP(HBITMAP hbmColor,INT x,INT y,HBITMAP hbmMask)1629afcbea2SKatayama Hirofumi MZ void SelectionModel::InsertFromHBITMAP(HBITMAP hbmColor, INT x, INT y, HBITMAP hbmMask)
163c2c66affSColin Finck {
164aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor);
165b5335fb9SKatayama Hirofumi MZ m_hbmColor = hbmColor;
166c2c66affSColin Finck
167aac89519SKatayama Hirofumi MZ m_rc.left = x;
168aac89519SKatayama Hirofumi MZ m_rc.top = y;
1699afcbea2SKatayama Hirofumi MZ m_rc.right = x + GetDIBWidth(hbmColor);
1709afcbea2SKatayama Hirofumi MZ m_rc.bottom = y + GetDIBHeight(hbmColor);
1719afcbea2SKatayama Hirofumi MZ
1729afcbea2SKatayama Hirofumi MZ if (hbmMask)
1739afcbea2SKatayama Hirofumi MZ {
1749afcbea2SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask);
175b5335fb9SKatayama Hirofumi MZ m_hbmMask = hbmMask;
1769afcbea2SKatayama Hirofumi MZ }
1779afcbea2SKatayama Hirofumi MZ else
1789afcbea2SKatayama Hirofumi MZ {
179ed9973f8SKatayama Hirofumi MZ ClearMaskImage();
1809afcbea2SKatayama Hirofumi MZ }
1819f56e67bSKatayama Hirofumi MZ
1827aadc1e1SKatayama Hirofumi MZ NotifyContentChanged();
183c2c66affSColin Finck }
184c2c66affSColin Finck
FlipHorizontally()185c2c66affSColin Finck void SelectionModel::FlipHorizontally()
186c2c66affSColin Finck {
187aac89519SKatayama Hirofumi MZ TakeOff();
188aac89519SKatayama Hirofumi MZ
189aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL);
190aac89519SKatayama Hirofumi MZ if (m_hbmMask)
191aac89519SKatayama Hirofumi MZ {
192aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmMask);
193aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
194aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
195aac89519SKatayama Hirofumi MZ }
196aac89519SKatayama Hirofumi MZ if (m_hbmColor)
197aac89519SKatayama Hirofumi MZ {
198aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmColor);
199aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
200aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
201aac89519SKatayama Hirofumi MZ }
202aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem);
203aac89519SKatayama Hirofumi MZ
2047aadc1e1SKatayama Hirofumi MZ NotifyContentChanged();
205c2c66affSColin Finck }
206c2c66affSColin Finck
FlipVertically()207c2c66affSColin Finck void SelectionModel::FlipVertically()
208c2c66affSColin Finck {
209aac89519SKatayama Hirofumi MZ TakeOff();
210aac89519SKatayama Hirofumi MZ
211aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL);
212aac89519SKatayama Hirofumi MZ if (m_hbmMask)
213aac89519SKatayama Hirofumi MZ {
214aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmMask);
215aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
216aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
217aac89519SKatayama Hirofumi MZ }
218aac89519SKatayama Hirofumi MZ if (m_hbmColor)
219aac89519SKatayama Hirofumi MZ {
220aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmColor);
221aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
222aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
223aac89519SKatayama Hirofumi MZ }
224aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem);
225aac89519SKatayama Hirofumi MZ
2267aadc1e1SKatayama Hirofumi MZ NotifyContentChanged();
227c2c66affSColin Finck }
228c2c66affSColin Finck
RotateNTimes90Degrees(int iN)229c2c66affSColin Finck void SelectionModel::RotateNTimes90Degrees(int iN)
230c2c66affSColin Finck {
2312d909190SKatayama Hirofumi MZ HBITMAP hbm;
232aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld;
233aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL);
234aac89519SKatayama Hirofumi MZ
2352d909190SKatayama Hirofumi MZ switch (iN)
236c2c66affSColin Finck {
2377aadc1e1SKatayama Hirofumi MZ case 1: /* rotate 90 degrees */
2387aadc1e1SKatayama Hirofumi MZ case 3: /* rotate 270 degrees */
239aac89519SKatayama Hirofumi MZ TakeOff();
2407aadc1e1SKatayama Hirofumi MZ
241aac89519SKatayama Hirofumi MZ if (m_hbmColor)
242aac89519SKatayama Hirofumi MZ {
243aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmColor);
244aac89519SKatayama Hirofumi MZ hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, FALSE);
245aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld);
246aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor);
247aac89519SKatayama Hirofumi MZ m_hbmColor = hbm;
248aac89519SKatayama Hirofumi MZ }
249aac89519SKatayama Hirofumi MZ if (m_hbmMask)
250aac89519SKatayama Hirofumi MZ {
251aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
252aac89519SKatayama Hirofumi MZ hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, TRUE);
253aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld);
254aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask);
255aac89519SKatayama Hirofumi MZ m_hbmMask = hbm;
256aac89519SKatayama Hirofumi MZ }
2577aadc1e1SKatayama Hirofumi MZ
2587aadc1e1SKatayama Hirofumi MZ SwapWidthAndHeight();
2592d909190SKatayama Hirofumi MZ break;
260aac89519SKatayama Hirofumi MZ
2617aadc1e1SKatayama Hirofumi MZ case 2: /* rotate 180 degrees */
262aac89519SKatayama Hirofumi MZ TakeOff();
2637aadc1e1SKatayama Hirofumi MZ
264aac89519SKatayama Hirofumi MZ if (m_hbmColor)
265aac89519SKatayama Hirofumi MZ {
266aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmColor);
267aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
268aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
269aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld);
270aac89519SKatayama Hirofumi MZ }
271aac89519SKatayama Hirofumi MZ if (m_hbmMask)
272aac89519SKatayama Hirofumi MZ {
273aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
274aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
275aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
276aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld);
277aac89519SKatayama Hirofumi MZ }
2782d909190SKatayama Hirofumi MZ break;
279c2c66affSColin Finck }
280aac89519SKatayama Hirofumi MZ
281aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem);
2827aadc1e1SKatayama Hirofumi MZ NotifyContentChanged();
283c2c66affSColin Finck }
284c2c66affSColin Finck
AttachHBITMAP(HBITMAP * phbm,HBITMAP hbmNew)285b5335fb9SKatayama Hirofumi MZ static void AttachHBITMAP(HBITMAP *phbm, HBITMAP hbmNew)
286b5335fb9SKatayama Hirofumi MZ {
287b5335fb9SKatayama Hirofumi MZ if (hbmNew == NULL)
288b5335fb9SKatayama Hirofumi MZ return;
289b5335fb9SKatayama Hirofumi MZ ::DeleteObject(*phbm);
290b5335fb9SKatayama Hirofumi MZ *phbm = hbmNew;
291b5335fb9SKatayama Hirofumi MZ }
292b5335fb9SKatayama Hirofumi MZ
StretchSkew(int nStretchPercentX,int nStretchPercentY,int nSkewDegX,int nSkewDegY)293dfd06ee8SKatayama Hirofumi MZ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
294dfd06ee8SKatayama Hirofumi MZ {
295dfd06ee8SKatayama Hirofumi MZ if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
296dfd06ee8SKatayama Hirofumi MZ return;
297dfd06ee8SKatayama Hirofumi MZ
298aac89519SKatayama Hirofumi MZ TakeOff();
299dfd06ee8SKatayama Hirofumi MZ
300b5335fb9SKatayama Hirofumi MZ INT oldWidth = m_rc.Width(), oldHeight = m_rc.Height();
301dfd06ee8SKatayama Hirofumi MZ INT newWidth = oldWidth * nStretchPercentX / 100;
302dfd06ee8SKatayama Hirofumi MZ INT newHeight = oldHeight * nStretchPercentY / 100;
303dfd06ee8SKatayama Hirofumi MZ
304b5335fb9SKatayama Hirofumi MZ HBITMAP hbmColor = m_hbmColor, hbmMask = m_hbmMask;
3059afcbea2SKatayama Hirofumi MZ
306b5335fb9SKatayama Hirofumi MZ if (hbmMask == NULL)
307b5335fb9SKatayama Hirofumi MZ hbmMask = CreateMonoBitmap(oldWidth, oldHeight, TRUE);
3089afcbea2SKatayama Hirofumi MZ
309dfd06ee8SKatayama Hirofumi MZ if (oldWidth != newWidth || oldHeight != newHeight)
310dfd06ee8SKatayama Hirofumi MZ {
311b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, CopyDIBImage(hbmColor, newWidth, newHeight));
312b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, CopyMonoImage(hbmMask, newWidth, newHeight));
313dfd06ee8SKatayama Hirofumi MZ }
314dfd06ee8SKatayama Hirofumi MZ
315b5335fb9SKatayama Hirofumi MZ HGDIOBJ hbmOld;
316aac89519SKatayama Hirofumi MZ HDC hDC = ::CreateCompatibleDC(NULL);
317aac89519SKatayama Hirofumi MZ
318dfd06ee8SKatayama Hirofumi MZ if (nSkewDegX)
319dfd06ee8SKatayama Hirofumi MZ {
320b5335fb9SKatayama Hirofumi MZ hbmOld = ::SelectObject(hDC, hbmColor);
321b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegX, FALSE));
322b5335fb9SKatayama Hirofumi MZ ::SelectObject(hDC, hbmMask);
323b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegX, FALSE, TRUE));
3249afcbea2SKatayama Hirofumi MZ ::SelectObject(hDC, hbmOld);
325dfd06ee8SKatayama Hirofumi MZ }
326dfd06ee8SKatayama Hirofumi MZ
327dfd06ee8SKatayama Hirofumi MZ if (nSkewDegY)
328dfd06ee8SKatayama Hirofumi MZ {
329b5335fb9SKatayama Hirofumi MZ hbmOld = ::SelectObject(hDC, hbmColor);
330b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegY, TRUE));
331b5335fb9SKatayama Hirofumi MZ ::SelectObject(hDC, hbmMask);
332b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegY, TRUE, TRUE));
3339afcbea2SKatayama Hirofumi MZ ::SelectObject(hDC, hbmOld);
334dfd06ee8SKatayama Hirofumi MZ }
335dfd06ee8SKatayama Hirofumi MZ
336aac89519SKatayama Hirofumi MZ ::DeleteDC(hDC);
337aac89519SKatayama Hirofumi MZ
338b5335fb9SKatayama Hirofumi MZ InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask);
339b5335fb9SKatayama Hirofumi MZ
340aac89519SKatayama Hirofumi MZ m_bShow = TRUE;
3417aadc1e1SKatayama Hirofumi MZ NotifyContentChanged();
342dfd06ee8SKatayama Hirofumi MZ }
343dfd06ee8SKatayama Hirofumi MZ
SetRectFromPoints(const POINT & ptFrom,const POINT & ptTo)344aac89519SKatayama Hirofumi MZ void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
345c2c66affSColin Finck {
3461aeebfdaSKatayama Hirofumi MZ m_rc = CRect(ptFrom, ptTo);
3471aeebfdaSKatayama Hirofumi MZ m_rc.NormalizeRect();
348c2c66affSColin Finck }
349c2c66affSColin Finck
Dragging(HITTEST hit,POINT pt)350cb98e91bSKatayama Hirofumi MZ void SelectionModel::Dragging(HITTEST hit, POINT pt)
351c2c66affSColin Finck {
352aac89519SKatayama Hirofumi MZ switch (hit)
353c2c66affSColin Finck {
354aac89519SKatayama Hirofumi MZ case HIT_NONE:
355c2c66affSColin Finck break;
356aac89519SKatayama Hirofumi MZ case HIT_UPPER_LEFT:
357aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x;
358aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y;
359c2c66affSColin Finck break;
360aac89519SKatayama Hirofumi MZ case HIT_UPPER_CENTER:
361aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y;
362c2c66affSColin Finck break;
363aac89519SKatayama Hirofumi MZ case HIT_UPPER_RIGHT:
364aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x;
365aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y;
366c2c66affSColin Finck break;
367aac89519SKatayama Hirofumi MZ case HIT_MIDDLE_LEFT:
368aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x;
369c2c66affSColin Finck break;
370aac89519SKatayama Hirofumi MZ case HIT_MIDDLE_RIGHT:
371aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x;
372c2c66affSColin Finck break;
373aac89519SKatayama Hirofumi MZ case HIT_LOWER_LEFT:
374aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x;
375aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y;
376c2c66affSColin Finck break;
377aac89519SKatayama Hirofumi MZ case HIT_LOWER_CENTER:
378aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y;
379c2c66affSColin Finck break;
380aac89519SKatayama Hirofumi MZ case HIT_LOWER_RIGHT:
381aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x;
382aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y;
383aac89519SKatayama Hirofumi MZ break;
384aac89519SKatayama Hirofumi MZ case HIT_BORDER:
385aac89519SKatayama Hirofumi MZ case HIT_INNER:
3861aeebfdaSKatayama Hirofumi MZ m_rc.OffsetRect(pt.x - m_ptHit.x, pt.y - m_ptHit.y);
387c2c66affSColin Finck break;
388c2c66affSColin Finck }
389aac89519SKatayama Hirofumi MZ m_ptHit = pt;
390c2c66affSColin Finck }
391c2c66affSColin Finck
ClearMaskImage()392ed9973f8SKatayama Hirofumi MZ void SelectionModel::ClearMaskImage()
393361a2ce4SKatayama Hirofumi MZ {
394aac89519SKatayama Hirofumi MZ if (m_hbmMask)
395aac89519SKatayama Hirofumi MZ {
396aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask);
397aac89519SKatayama Hirofumi MZ m_hbmMask = NULL;
398aac89519SKatayama Hirofumi MZ }
399aac89519SKatayama Hirofumi MZ }
400aac89519SKatayama Hirofumi MZ
ClearColorImage()401ed9973f8SKatayama Hirofumi MZ void SelectionModel::ClearColorImage()
402aac89519SKatayama Hirofumi MZ {
403aac89519SKatayama Hirofumi MZ if (m_hbmColor)
404aac89519SKatayama Hirofumi MZ {
405aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor);
406aac89519SKatayama Hirofumi MZ m_hbmColor = NULL;
407aac89519SKatayama Hirofumi MZ }
408aac89519SKatayama Hirofumi MZ }
409aac89519SKatayama Hirofumi MZ
HideSelection()410e8c7e300SKatayama Hirofumi MZ void SelectionModel::HideSelection()
411e8c7e300SKatayama Hirofumi MZ {
4127aadc1e1SKatayama Hirofumi MZ m_bShow = m_bContentChanged = FALSE;
413ed9973f8SKatayama Hirofumi MZ ClearColorImage();
414ed9973f8SKatayama Hirofumi MZ ClearMaskImage();
4151aeebfdaSKatayama Hirofumi MZ m_rc.SetRectEmpty();
4161aeebfdaSKatayama Hirofumi MZ m_rcOld.SetRectEmpty();
417e8c7e300SKatayama Hirofumi MZ imageModel.NotifyImageChanged();
418e8c7e300SKatayama Hirofumi MZ }
419e8c7e300SKatayama Hirofumi MZ
DeleteSelection()420e8c7e300SKatayama Hirofumi MZ void SelectionModel::DeleteSelection()
421aac89519SKatayama Hirofumi MZ {
422aac89519SKatayama Hirofumi MZ if (!m_bShow)
423aac89519SKatayama Hirofumi MZ return;
424aac89519SKatayama Hirofumi MZ
425e8c7e300SKatayama Hirofumi MZ TakeOff();
426e8c7e300SKatayama Hirofumi MZ imageModel.PushImageForUndo();
427b8598e09SKatayama Hirofumi MZ DrawBackground(imageModel.GetDC(), paletteModel.GetBgColor());
428e8c7e300SKatayama Hirofumi MZ
429e8c7e300SKatayama Hirofumi MZ HideSelection();
430361a2ce4SKatayama Hirofumi MZ }
4317aadc1e1SKatayama Hirofumi MZ
InvertSelection()4327aadc1e1SKatayama Hirofumi MZ void SelectionModel::InvertSelection()
4337aadc1e1SKatayama Hirofumi MZ {
4347aadc1e1SKatayama Hirofumi MZ TakeOff();
4357aadc1e1SKatayama Hirofumi MZ
4367aadc1e1SKatayama Hirofumi MZ BITMAP bm;
437640d67d1SKatayama Hirofumi MZ ::GetObjectW(m_hbmColor, sizeof(bm), &bm);
4387aadc1e1SKatayama Hirofumi MZ
4397aadc1e1SKatayama Hirofumi MZ HDC hdc = ::CreateCompatibleDC(NULL);
4407aadc1e1SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hdc, m_hbmColor);
4417aadc1e1SKatayama Hirofumi MZ RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight };
4427aadc1e1SKatayama Hirofumi MZ ::InvertRect(hdc, &rc);
4437aadc1e1SKatayama Hirofumi MZ ::SelectObject(hdc, hbmOld);
4447aadc1e1SKatayama Hirofumi MZ ::DeleteDC(hdc);
4457aadc1e1SKatayama Hirofumi MZ
4467aadc1e1SKatayama Hirofumi MZ NotifyContentChanged();
4477aadc1e1SKatayama Hirofumi MZ }
4487aadc1e1SKatayama Hirofumi MZ
NotifyContentChanged()4497aadc1e1SKatayama Hirofumi MZ void SelectionModel::NotifyContentChanged()
4507aadc1e1SKatayama Hirofumi MZ {
4517aadc1e1SKatayama Hirofumi MZ m_bContentChanged = TRUE;
4527aadc1e1SKatayama Hirofumi MZ imageModel.NotifyImageChanged();
4537aadc1e1SKatayama Hirofumi MZ }
4547aadc1e1SKatayama Hirofumi MZ
SwapWidthAndHeight()4557aadc1e1SKatayama Hirofumi MZ void SelectionModel::SwapWidthAndHeight()
4567aadc1e1SKatayama Hirofumi MZ {
4574a52a4b0SKatayama Hirofumi MZ INT cx = m_rc.Width(), cy = m_rc.Height();
4587aadc1e1SKatayama Hirofumi MZ m_rc.right = m_rc.left + cy;
4597aadc1e1SKatayama Hirofumi MZ m_rc.bottom = m_rc.top + cx;
4607aadc1e1SKatayama Hirofumi MZ }
461bbb33a6eSKatayama Hirofumi MZ
hitTest(POINT ptCanvas)462c2bb5aa0SKatayama Hirofumi MZ HITTEST SelectionModel::hitTest(POINT ptCanvas)
463c2bb5aa0SKatayama Hirofumi MZ {
464c2bb5aa0SKatayama Hirofumi MZ if (!m_bShow)
465c2bb5aa0SKatayama Hirofumi MZ return HIT_NONE;
466c2bb5aa0SKatayama Hirofumi MZ
4671aeebfdaSKatayama Hirofumi MZ CRect rcSelection = m_rc;
468c2bb5aa0SKatayama Hirofumi MZ canvasWindow.ImageToCanvas(rcSelection);
4691aeebfdaSKatayama Hirofumi MZ rcSelection.InflateRect(GRIP_SIZE, GRIP_SIZE);
470c2bb5aa0SKatayama Hirofumi MZ return getSizeBoxHitTest(ptCanvas, &rcSelection);
471c2bb5aa0SKatayama Hirofumi MZ }
472c2bb5aa0SKatayama Hirofumi MZ
drawFrameOnCanvas(HDC hCanvasDC)4734a52a4b0SKatayama Hirofumi MZ void SelectionModel::drawFrameOnCanvas(HDC hCanvasDC)
4744a52a4b0SKatayama Hirofumi MZ {
4754a52a4b0SKatayama Hirofumi MZ if (!m_bShow)
4764a52a4b0SKatayama Hirofumi MZ return;
4774a52a4b0SKatayama Hirofumi MZ
4781aeebfdaSKatayama Hirofumi MZ CRect rcSelection = m_rc;
4794a52a4b0SKatayama Hirofumi MZ canvasWindow.ImageToCanvas(rcSelection);
4801aeebfdaSKatayama Hirofumi MZ rcSelection.InflateRect(GRIP_SIZE, GRIP_SIZE);
4814a52a4b0SKatayama Hirofumi MZ drawSizeBoxes(hCanvasDC, &rcSelection, TRUE);
4824a52a4b0SKatayama Hirofumi MZ }
4834a52a4b0SKatayama Hirofumi MZ
moveSelection(INT xDelta,INT yDelta)484f935132fSKatayama Hirofumi MZ void SelectionModel::moveSelection(INT xDelta, INT yDelta)
485f935132fSKatayama Hirofumi MZ {
486f935132fSKatayama Hirofumi MZ if (!m_bShow)
487f935132fSKatayama Hirofumi MZ return;
488f935132fSKatayama Hirofumi MZ
489f935132fSKatayama Hirofumi MZ TakeOff();
4901aeebfdaSKatayama Hirofumi MZ m_rc.OffsetRect(xDelta, yDelta);
491f935132fSKatayama Hirofumi MZ canvasWindow.Invalidate();
492f935132fSKatayama Hirofumi MZ }
493f935132fSKatayama Hirofumi MZ
StretchSelection(BOOL bShrink)494ed9973f8SKatayama Hirofumi MZ void SelectionModel::StretchSelection(BOOL bShrink)
495ed9973f8SKatayama Hirofumi MZ {
496ed9973f8SKatayama Hirofumi MZ if (!m_bShow)
497ed9973f8SKatayama Hirofumi MZ return;
498ed9973f8SKatayama Hirofumi MZ
499ed9973f8SKatayama Hirofumi MZ TakeOff();
500ed9973f8SKatayama Hirofumi MZ
501ed9973f8SKatayama Hirofumi MZ INT cx = m_rc.Width(), cy = m_rc.Height();
502ed9973f8SKatayama Hirofumi MZ
503ed9973f8SKatayama Hirofumi MZ if (bShrink)
504ed9973f8SKatayama Hirofumi MZ m_rc.InflateRect(-cx / 4, -cy / 4);
505ed9973f8SKatayama Hirofumi MZ else
506ed9973f8SKatayama Hirofumi MZ m_rc.InflateRect(+cx / 2, +cy / 2);
507ed9973f8SKatayama Hirofumi MZ
508ed9973f8SKatayama Hirofumi MZ // The selection area must exist there
509ed9973f8SKatayama Hirofumi MZ if (m_rc.Width() <= 0)
510ed9973f8SKatayama Hirofumi MZ m_rc.right = m_rc.left + 1;
511ed9973f8SKatayama Hirofumi MZ if (m_rc.Height() <= 0)
512ed9973f8SKatayama Hirofumi MZ m_rc.bottom = m_rc.top + 1;
513ed9973f8SKatayama Hirofumi MZ
514ed9973f8SKatayama Hirofumi MZ imageModel.NotifyImageChanged();
515ed9973f8SKatayama Hirofumi MZ }
516