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