1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:     PAINT for ReactOS
3c2c66affSColin Finck  * LICENSE:     LGPL
4c2c66affSColin Finck  * FILE:        base/applications/mspaint/selectionmodel.cpp
5c2c66affSColin Finck  * PURPOSE:     Keep track of selection parameters, notify listeners
6c2c66affSColin Finck  * PROGRAMMERS: Benedikt Freisen
73fa95ab9SKatayama Hirofumi MZ  *              Katayama Hirofumi MZ
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck #include "precomp.h"
11c2c66affSColin Finck 
1229e147beSKatayama Hirofumi MZ SelectionModel selectionModel;
1329e147beSKatayama Hirofumi MZ 
14c2c66affSColin Finck /* FUNCTIONS ********************************************************/
15c2c66affSColin Finck 
16c2c66affSColin Finck SelectionModel::SelectionModel()
17aac89519SKatayama Hirofumi MZ     : m_hbmColor(NULL)
18aac89519SKatayama Hirofumi MZ     , m_hbmMask(NULL)
193fa95ab9SKatayama Hirofumi MZ     , m_ptStack(NULL)
203fa95ab9SKatayama Hirofumi MZ     , m_iPtSP(0)
21*17bdf554SKatayama Hirofumi MZ     , m_rgbBack(RGB(255, 255, 255))
22aac89519SKatayama Hirofumi MZ     , m_bShow(FALSE)
237aadc1e1SKatayama Hirofumi MZ     , m_bContentChanged(FALSE)
24c2c66affSColin Finck {
25aac89519SKatayama Hirofumi MZ     ::SetRectEmpty(&m_rc);
26e8c7e300SKatayama Hirofumi MZ     ::SetRectEmpty(&m_rcOld);
27aac89519SKatayama Hirofumi MZ     m_ptHit.x = m_ptHit.y = -1;
283fa95ab9SKatayama Hirofumi MZ }
29c2c66affSColin Finck 
303fa95ab9SKatayama Hirofumi MZ SelectionModel::~SelectionModel()
313fa95ab9SKatayama Hirofumi MZ {
32aac89519SKatayama Hirofumi MZ     ClearColor();
33aac89519SKatayama Hirofumi MZ     ClearMask();
343fa95ab9SKatayama Hirofumi MZ     ResetPtStack();
35c2c66affSColin Finck }
36c2c66affSColin Finck 
37c2c66affSColin Finck void SelectionModel::ResetPtStack()
38c2c66affSColin Finck {
39aac89519SKatayama Hirofumi MZ     if (m_ptStack)
40aac89519SKatayama Hirofumi MZ     {
41aac89519SKatayama Hirofumi MZ         free(m_ptStack);
42c2c66affSColin Finck         m_ptStack = NULL;
43aac89519SKatayama Hirofumi MZ     }
44c2c66affSColin Finck     m_iPtSP = 0;
45c2c66affSColin Finck }
46c2c66affSColin Finck 
47aac89519SKatayama Hirofumi MZ void SelectionModel::PushToPtStack(POINT pt)
48c2c66affSColin Finck {
49aac89519SKatayama Hirofumi MZ #define GROW_COUNT 256
50aac89519SKatayama Hirofumi MZ     if (m_iPtSP % GROW_COUNT == 0)
51c2c66affSColin Finck     {
52aac89519SKatayama Hirofumi MZ         INT nNewCount = m_iPtSP + GROW_COUNT;
53aac89519SKatayama Hirofumi MZ         LPPOINT pptNew = (LPPOINT)realloc(m_ptStack, sizeof(POINT) * nNewCount);
54aac89519SKatayama Hirofumi MZ         if (pptNew == NULL)
55aac89519SKatayama Hirofumi MZ             return;
56aac89519SKatayama Hirofumi MZ         m_ptStack = pptNew;
57c2c66affSColin Finck     }
58aac89519SKatayama Hirofumi MZ     m_ptStack[m_iPtSP] = pt;
59c2c66affSColin Finck     m_iPtSP++;
60aac89519SKatayama Hirofumi MZ #undef GROW_COUNT
61c2c66affSColin Finck }
62c2c66affSColin Finck 
63e8c7e300SKatayama Hirofumi MZ void SelectionModel::ShiftPtStack(INT dx, INT dy)
64c2c66affSColin Finck {
65aac89519SKatayama Hirofumi MZ     for (INT i = 0; i < m_iPtSP; ++i)
66aac89519SKatayama Hirofumi MZ     {
67aac89519SKatayama Hirofumi MZ         POINT& pt = m_ptStack[i];
68e8c7e300SKatayama Hirofumi MZ         pt.x += dx;
69e8c7e300SKatayama Hirofumi MZ         pt.y += dy;
70c2c66affSColin Finck     }
71c2c66affSColin Finck }
72c2c66affSColin Finck 
73aac89519SKatayama Hirofumi MZ void SelectionModel::BuildMaskFromPtStack()
74c2c66affSColin Finck {
75aac89519SKatayama Hirofumi MZ     CRect rc = { MAXLONG, MAXLONG, 0, 0 };
76aac89519SKatayama Hirofumi MZ     for (INT i = 0; i < m_iPtSP; ++i)
77aac89519SKatayama Hirofumi MZ     {
78aac89519SKatayama Hirofumi MZ         POINT& pt = m_ptStack[i];
79aac89519SKatayama Hirofumi MZ         rc.left = min(pt.x, rc.left);
80aac89519SKatayama Hirofumi MZ         rc.top = min(pt.y, rc.top);
81aac89519SKatayama Hirofumi MZ         rc.right = max(pt.x, rc.right);
82aac89519SKatayama Hirofumi MZ         rc.bottom = max(pt.y, rc.bottom);
83aac89519SKatayama Hirofumi MZ     }
84aac89519SKatayama Hirofumi MZ     rc.right += 1;
85aac89519SKatayama Hirofumi MZ     rc.bottom += 1;
86aac89519SKatayama Hirofumi MZ 
87e8c7e300SKatayama Hirofumi MZ     m_rc = m_rcOld = rc;
88aac89519SKatayama Hirofumi MZ 
89aac89519SKatayama Hirofumi MZ     ClearMask();
90aac89519SKatayama Hirofumi MZ 
91e8c7e300SKatayama Hirofumi MZ     ShiftPtStack(-m_rcOld.left, -m_rcOld.top);
92e8c7e300SKatayama Hirofumi MZ 
93aac89519SKatayama Hirofumi MZ     HDC hdcMem = ::CreateCompatibleDC(NULL);
94aac89519SKatayama Hirofumi MZ     m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
95aac89519SKatayama Hirofumi MZ     HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
96e8c7e300SKatayama Hirofumi MZ     ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
97aac89519SKatayama Hirofumi MZ     HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
98aac89519SKatayama Hirofumi MZ     HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
99aac89519SKatayama Hirofumi MZ     ::Polygon(hdcMem, m_ptStack, m_iPtSP);
100aac89519SKatayama Hirofumi MZ     ::SelectObject(hdcMem, hbrOld);
101aac89519SKatayama Hirofumi MZ     ::SelectObject(hdcMem, hPenOld);
102aac89519SKatayama Hirofumi MZ     ::SelectObject(hdcMem, hbmOld);
103aac89519SKatayama Hirofumi MZ     ::DeleteDC(hdcMem);
104e8c7e300SKatayama Hirofumi MZ 
105e8c7e300SKatayama Hirofumi MZ     ShiftPtStack(+m_rcOld.left, +m_rcOld.top);
106c2c66affSColin Finck }
107c2c66affSColin Finck 
108c2c66affSColin Finck void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
109c2c66affSColin Finck {
110e8c7e300SKatayama Hirofumi MZ     if (::IsRectEmpty(&m_rcOld))
111e8c7e300SKatayama Hirofumi MZ         return;
112aac89519SKatayama Hirofumi MZ 
113aac89519SKatayama Hirofumi MZ     HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN));
114aac89519SKatayama Hirofumi MZ     HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg));
115aac89519SKatayama Hirofumi MZ     ::Polygon(hDCImage, m_ptStack, m_iPtSP);
116aac89519SKatayama Hirofumi MZ     ::DeleteObject(::SelectObject(hDCImage, hbrOld));
117aac89519SKatayama Hirofumi MZ     ::SelectObject(hDCImage, hPenOld);
118c2c66affSColin Finck }
119c2c66affSColin Finck 
120c2c66affSColin Finck void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
121c2c66affSColin Finck {
122e8c7e300SKatayama Hirofumi MZ     if (::IsRectEmpty(&m_rcOld))
123e8c7e300SKatayama Hirofumi MZ         return;
124e8c7e300SKatayama Hirofumi MZ 
125e8c7e300SKatayama Hirofumi MZ     Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1);
126c2c66affSColin Finck }
127c2c66affSColin Finck 
1287aadc1e1SKatayama Hirofumi MZ void SelectionModel::DrawBackground(HDC hDCImage)
1297aadc1e1SKatayama Hirofumi MZ {
1307aadc1e1SKatayama Hirofumi MZ     if (toolsModel.GetActiveTool() == TOOL_FREESEL)
1317aadc1e1SKatayama Hirofumi MZ         DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
1327aadc1e1SKatayama Hirofumi MZ     else
1337aadc1e1SKatayama Hirofumi MZ         DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
1347aadc1e1SKatayama Hirofumi MZ }
1357aadc1e1SKatayama Hirofumi MZ 
136e8c7e300SKatayama Hirofumi MZ void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
137c2c66affSColin Finck {
138e8c7e300SKatayama Hirofumi MZ     CRect rc = m_rc;
139aac89519SKatayama Hirofumi MZ     if (::IsRectEmpty(&rc))
140aac89519SKatayama Hirofumi MZ         return;
141aac89519SKatayama Hirofumi MZ 
142aac89519SKatayama Hirofumi MZ     BITMAP bm;
143e8c7e300SKatayama Hirofumi MZ     if (!GetObject(m_hbmColor, sizeof(BITMAP), &bm))
144e8c7e300SKatayama Hirofumi MZ         return;
145aac89519SKatayama Hirofumi MZ 
146aac89519SKatayama Hirofumi MZ     COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
147aac89519SKatayama Hirofumi MZ 
148aac89519SKatayama Hirofumi MZ     HDC hMemDC = CreateCompatibleDC(hDCImage);
149aac89519SKatayama Hirofumi MZ     HGDIOBJ hbmOld = SelectObject(hMemDC, m_hbmColor);
150aac89519SKatayama Hirofumi MZ     ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(),
151aac89519SKatayama Hirofumi MZ                       hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor);
152aac89519SKatayama Hirofumi MZ     SelectObject(hMemDC, hbmOld);
153aac89519SKatayama Hirofumi MZ     DeleteDC(hMemDC);
154aac89519SKatayama Hirofumi MZ }
155aac89519SKatayama Hirofumi MZ 
156aac89519SKatayama Hirofumi MZ void SelectionModel::GetSelectionContents(HDC hDCImage)
157aac89519SKatayama Hirofumi MZ {
158aac89519SKatayama Hirofumi MZ     ClearColor();
159aac89519SKatayama Hirofumi MZ 
160aac89519SKatayama Hirofumi MZ     HDC hMemDC = ::CreateCompatibleDC(NULL);
161aac89519SKatayama Hirofumi MZ     m_hbmColor = CreateColorDIB(m_rc.Width(), m_rc.Height(), RGB(255, 255, 255));
162aac89519SKatayama Hirofumi MZ     HGDIOBJ hbmOld = ::SelectObject(hMemDC, m_hbmColor);
163aac89519SKatayama Hirofumi MZ     ::BitBlt(hMemDC, 0, 0, m_rc.Width(), m_rc.Height(), hDCImage, m_rc.left, m_rc.top, SRCCOPY);
164aac89519SKatayama Hirofumi MZ     ::SelectObject(hMemDC, hbmOld);
165aac89519SKatayama Hirofumi MZ     ::DeleteDC(hMemDC);
166aac89519SKatayama Hirofumi MZ }
167aac89519SKatayama Hirofumi MZ 
168e8c7e300SKatayama Hirofumi MZ BOOL SelectionModel::IsLanded() const
169e8c7e300SKatayama Hirofumi MZ {
170e8c7e300SKatayama Hirofumi MZ     return !m_hbmColor;
171e8c7e300SKatayama Hirofumi MZ }
172e8c7e300SKatayama Hirofumi MZ 
173aac89519SKatayama Hirofumi MZ BOOL SelectionModel::TakeOff()
174aac89519SKatayama Hirofumi MZ {
175e8c7e300SKatayama Hirofumi MZ     if (!IsLanded() || ::IsRectEmpty(&m_rc))
176aac89519SKatayama Hirofumi MZ         return FALSE;
177aac89519SKatayama Hirofumi MZ 
178e8c7e300SKatayama Hirofumi MZ     m_rgbBack = paletteModel.GetBgColor();
179e8c7e300SKatayama Hirofumi MZ     GetSelectionContents(imageModel.GetDC());
180aac89519SKatayama Hirofumi MZ 
181e8c7e300SKatayama Hirofumi MZ     if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
182aac89519SKatayama Hirofumi MZ         ClearMask();
183e8c7e300SKatayama Hirofumi MZ 
184e8c7e300SKatayama Hirofumi MZ     m_rcOld = m_rc;
185c2c66affSColin Finck 
186bfd42c67SKatayama Hirofumi MZ     imageModel.NotifyImageChanged();
187aac89519SKatayama Hirofumi MZ     return TRUE;
188c2c66affSColin Finck }
189c2c66affSColin Finck 
190aac89519SKatayama Hirofumi MZ void SelectionModel::Landing()
191c2c66affSColin Finck {
192e8c7e300SKatayama Hirofumi MZ     if (IsLanded() && !m_bShow)
193e8c7e300SKatayama Hirofumi MZ     {
194e8c7e300SKatayama Hirofumi MZ         imageModel.NotifyImageChanged();
195aac89519SKatayama Hirofumi MZ         return;
196e8c7e300SKatayama Hirofumi MZ     }
197aac89519SKatayama Hirofumi MZ 
198e8c7e300SKatayama Hirofumi MZ     m_bShow = FALSE;
199aac89519SKatayama Hirofumi MZ 
2007aadc1e1SKatayama Hirofumi MZ     if (m_bContentChanged ||
2017aadc1e1SKatayama Hirofumi MZ         (!::EqualRect(m_rc, m_rcOld) && !::IsRectEmpty(m_rc) && !::IsRectEmpty(m_rcOld)))
202e8c7e300SKatayama Hirofumi MZ     {
2032b623c1dSKatayama Hirofumi MZ         imageModel.PushImageForUndo();
204e8c7e300SKatayama Hirofumi MZ 
205e8c7e300SKatayama Hirofumi MZ         canvasWindow.m_drawing = FALSE;
206e8c7e300SKatayama Hirofumi MZ         toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
207e8c7e300SKatayama Hirofumi MZ     }
208e8c7e300SKatayama Hirofumi MZ 
209e8c7e300SKatayama Hirofumi MZ     HideSelection();
210c2c66affSColin Finck }
211c2c66affSColin Finck 
2122d909190SKatayama Hirofumi MZ void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
213c2c66affSColin Finck {
214aac89519SKatayama Hirofumi MZ     ::DeleteObject(m_hbmColor);
215639739a7SKatayama Hirofumi MZ     m_hbmColor = CopyDIBImage(hBm);
216c2c66affSColin Finck 
217aac89519SKatayama Hirofumi MZ     m_rc.left = x;
218aac89519SKatayama Hirofumi MZ     m_rc.top = y;
2199f56e67bSKatayama Hirofumi MZ     m_rc.right = x + GetDIBWidth(hBm);
2209f56e67bSKatayama Hirofumi MZ     m_rc.bottom = y + GetDIBHeight(hBm);
2219f56e67bSKatayama Hirofumi MZ 
2227aadc1e1SKatayama Hirofumi MZ     NotifyContentChanged();
223c2c66affSColin Finck 
224aac89519SKatayama Hirofumi MZ     ClearMask();
225c2c66affSColin Finck }
226c2c66affSColin Finck 
227c2c66affSColin Finck void SelectionModel::FlipHorizontally()
228c2c66affSColin Finck {
229aac89519SKatayama Hirofumi MZ     TakeOff();
230aac89519SKatayama Hirofumi MZ 
231aac89519SKatayama Hirofumi MZ     HDC hdcMem = ::CreateCompatibleDC(NULL);
232aac89519SKatayama Hirofumi MZ     if (m_hbmMask)
233aac89519SKatayama Hirofumi MZ     {
234aac89519SKatayama Hirofumi MZ         ::SelectObject(hdcMem, m_hbmMask);
235aac89519SKatayama Hirofumi MZ         ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
236aac89519SKatayama Hirofumi MZ                      hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
237aac89519SKatayama Hirofumi MZ     }
238aac89519SKatayama Hirofumi MZ     if (m_hbmColor)
239aac89519SKatayama Hirofumi MZ     {
240aac89519SKatayama Hirofumi MZ         ::SelectObject(hdcMem, m_hbmColor);
241aac89519SKatayama Hirofumi MZ         ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
242aac89519SKatayama Hirofumi MZ                      hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
243aac89519SKatayama Hirofumi MZ     }
244aac89519SKatayama Hirofumi MZ     ::DeleteDC(hdcMem);
245aac89519SKatayama Hirofumi MZ 
2467aadc1e1SKatayama Hirofumi MZ     NotifyContentChanged();
247c2c66affSColin Finck }
248c2c66affSColin Finck 
249c2c66affSColin Finck void SelectionModel::FlipVertically()
250c2c66affSColin Finck {
251aac89519SKatayama Hirofumi MZ     TakeOff();
252aac89519SKatayama Hirofumi MZ 
253aac89519SKatayama Hirofumi MZ     HDC hdcMem = ::CreateCompatibleDC(NULL);
254aac89519SKatayama Hirofumi MZ     if (m_hbmMask)
255aac89519SKatayama Hirofumi MZ     {
256aac89519SKatayama Hirofumi MZ         ::SelectObject(hdcMem, m_hbmMask);
257aac89519SKatayama Hirofumi MZ         ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
258aac89519SKatayama Hirofumi MZ                      hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
259aac89519SKatayama Hirofumi MZ     }
260aac89519SKatayama Hirofumi MZ     if (m_hbmColor)
261aac89519SKatayama Hirofumi MZ     {
262aac89519SKatayama Hirofumi MZ         ::SelectObject(hdcMem, m_hbmColor);
263aac89519SKatayama Hirofumi MZ         ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
264aac89519SKatayama Hirofumi MZ                      hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
265aac89519SKatayama Hirofumi MZ     }
266aac89519SKatayama Hirofumi MZ     ::DeleteDC(hdcMem);
267aac89519SKatayama Hirofumi MZ 
2687aadc1e1SKatayama Hirofumi MZ     NotifyContentChanged();
269c2c66affSColin Finck }
270c2c66affSColin Finck 
271c2c66affSColin Finck void SelectionModel::RotateNTimes90Degrees(int iN)
272c2c66affSColin Finck {
2732d909190SKatayama Hirofumi MZ     HBITMAP hbm;
274aac89519SKatayama Hirofumi MZ     HGDIOBJ hbmOld;
275aac89519SKatayama Hirofumi MZ     HDC hdcMem = ::CreateCompatibleDC(NULL);
276aac89519SKatayama Hirofumi MZ 
2772d909190SKatayama Hirofumi MZ     switch (iN)
278c2c66affSColin Finck     {
2797aadc1e1SKatayama Hirofumi MZ         case 1: /* rotate 90 degrees */
2807aadc1e1SKatayama Hirofumi MZ         case 3: /* rotate 270 degrees */
281aac89519SKatayama Hirofumi MZ             TakeOff();
2827aadc1e1SKatayama Hirofumi MZ 
283aac89519SKatayama Hirofumi MZ             if (m_hbmColor)
284aac89519SKatayama Hirofumi MZ             {
285aac89519SKatayama Hirofumi MZ                 hbmOld = ::SelectObject(hdcMem, m_hbmColor);
286aac89519SKatayama Hirofumi MZ                 hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, FALSE);
287aac89519SKatayama Hirofumi MZ                 ::SelectObject(hdcMem, hbmOld);
288aac89519SKatayama Hirofumi MZ                 ::DeleteObject(m_hbmColor);
289aac89519SKatayama Hirofumi MZ                 m_hbmColor = hbm;
290aac89519SKatayama Hirofumi MZ             }
291aac89519SKatayama Hirofumi MZ             if (m_hbmMask)
292aac89519SKatayama Hirofumi MZ             {
293aac89519SKatayama Hirofumi MZ                 hbmOld = ::SelectObject(hdcMem, m_hbmMask);
294aac89519SKatayama Hirofumi MZ                 hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, TRUE);
295aac89519SKatayama Hirofumi MZ                 ::SelectObject(hdcMem, hbmOld);
296aac89519SKatayama Hirofumi MZ                 ::DeleteObject(m_hbmMask);
297aac89519SKatayama Hirofumi MZ                 m_hbmMask = hbm;
298aac89519SKatayama Hirofumi MZ             }
2997aadc1e1SKatayama Hirofumi MZ 
3007aadc1e1SKatayama Hirofumi MZ             SwapWidthAndHeight();
3012d909190SKatayama Hirofumi MZ             break;
302aac89519SKatayama Hirofumi MZ 
3037aadc1e1SKatayama Hirofumi MZ         case 2: /* rotate 180 degrees */
304aac89519SKatayama Hirofumi MZ             TakeOff();
3057aadc1e1SKatayama Hirofumi MZ 
306aac89519SKatayama Hirofumi MZ             if (m_hbmColor)
307aac89519SKatayama Hirofumi MZ             {
308aac89519SKatayama Hirofumi MZ                 hbmOld = ::SelectObject(hdcMem, m_hbmColor);
309aac89519SKatayama Hirofumi MZ                 ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
310aac89519SKatayama Hirofumi MZ                              hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
311aac89519SKatayama Hirofumi MZ                 ::SelectObject(hdcMem, hbmOld);
312aac89519SKatayama Hirofumi MZ             }
313aac89519SKatayama Hirofumi MZ             if (m_hbmMask)
314aac89519SKatayama Hirofumi MZ             {
315aac89519SKatayama Hirofumi MZ                 hbmOld = ::SelectObject(hdcMem, m_hbmMask);
316aac89519SKatayama Hirofumi MZ                 ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
317aac89519SKatayama Hirofumi MZ                              hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
318aac89519SKatayama Hirofumi MZ                 ::SelectObject(hdcMem, hbmOld);
319aac89519SKatayama Hirofumi MZ             }
3202d909190SKatayama Hirofumi MZ             break;
321c2c66affSColin Finck     }
322aac89519SKatayama Hirofumi MZ 
323aac89519SKatayama Hirofumi MZ     ::DeleteDC(hdcMem);
3247aadc1e1SKatayama Hirofumi MZ     NotifyContentChanged();
325c2c66affSColin Finck }
326c2c66affSColin Finck 
327dfd06ee8SKatayama Hirofumi MZ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
328dfd06ee8SKatayama Hirofumi MZ {
329dfd06ee8SKatayama Hirofumi MZ     if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
330dfd06ee8SKatayama Hirofumi MZ         return;
331dfd06ee8SKatayama Hirofumi MZ 
332aac89519SKatayama Hirofumi MZ     TakeOff();
333dfd06ee8SKatayama Hirofumi MZ 
334aac89519SKatayama Hirofumi MZ     INT oldWidth = m_rc.Width();
335aac89519SKatayama Hirofumi MZ     INT oldHeight = m_rc.Height();
336dfd06ee8SKatayama Hirofumi MZ     INT newWidth = oldWidth * nStretchPercentX / 100;
337dfd06ee8SKatayama Hirofumi MZ     INT newHeight = oldHeight * nStretchPercentY / 100;
338dfd06ee8SKatayama Hirofumi MZ 
339dfd06ee8SKatayama Hirofumi MZ     if (oldWidth != newWidth || oldHeight != newHeight)
340dfd06ee8SKatayama Hirofumi MZ     {
341aac89519SKatayama Hirofumi MZ         HBITMAP hbm0 = CopyDIBImage(m_hbmColor, newWidth, newHeight);
342aac89519SKatayama Hirofumi MZ         InsertFromHBITMAP(hbm0, m_rc.left, m_rc.top);
343aac89519SKatayama Hirofumi MZ         ::DeleteObject(hbm0);
344dfd06ee8SKatayama Hirofumi MZ     }
345dfd06ee8SKatayama Hirofumi MZ 
346aac89519SKatayama Hirofumi MZ     HDC hDC = ::CreateCompatibleDC(NULL);
347aac89519SKatayama Hirofumi MZ 
348dfd06ee8SKatayama Hirofumi MZ     if (nSkewDegX)
349dfd06ee8SKatayama Hirofumi MZ     {
350aac89519SKatayama Hirofumi MZ         ::SelectObject(hDC, m_hbmColor);
351aac89519SKatayama Hirofumi MZ         HBITMAP hbm1 = SkewDIB(hDC, m_hbmColor, nSkewDegX, FALSE);
352aac89519SKatayama Hirofumi MZ         InsertFromHBITMAP(hbm1, m_rc.left, m_rc.top);
353aac89519SKatayama Hirofumi MZ         ::DeleteObject(hbm1);
354dfd06ee8SKatayama Hirofumi MZ     }
355dfd06ee8SKatayama Hirofumi MZ 
356dfd06ee8SKatayama Hirofumi MZ     if (nSkewDegY)
357dfd06ee8SKatayama Hirofumi MZ     {
358aac89519SKatayama Hirofumi MZ         ::SelectObject(hDC, m_hbmColor);
359aac89519SKatayama Hirofumi MZ         HBITMAP hbm2 = SkewDIB(hDC, m_hbmColor, nSkewDegY, TRUE);
360aac89519SKatayama Hirofumi MZ         InsertFromHBITMAP(hbm2, m_rc.left, m_rc.top);
361aac89519SKatayama Hirofumi MZ         ::DeleteObject(hbm2);
362dfd06ee8SKatayama Hirofumi MZ     }
363dfd06ee8SKatayama Hirofumi MZ 
364aac89519SKatayama Hirofumi MZ     ::DeleteDC(hDC);
365aac89519SKatayama Hirofumi MZ 
366aac89519SKatayama Hirofumi MZ     m_bShow = TRUE;
3677aadc1e1SKatayama Hirofumi MZ     NotifyContentChanged();
368dfd06ee8SKatayama Hirofumi MZ }
369dfd06ee8SKatayama Hirofumi MZ 
370e8c7e300SKatayama Hirofumi MZ HBITMAP SelectionModel::CopyBitmap()
371c2c66affSColin Finck {
37296c7fe4cSKatayama Hirofumi MZ     if (m_hbmColor == NULL)
37396c7fe4cSKatayama Hirofumi MZ         GetSelectionContents(imageModel.GetDC());
374e8c7e300SKatayama Hirofumi MZ     return CopyDIBImage(m_hbmColor);
375c2c66affSColin Finck }
376c2c66affSColin Finck 
377b5536e44SKatayama Hirofumi MZ int SelectionModel::PtStackSize() const
378c2c66affSColin Finck {
379c2c66affSColin Finck     return m_iPtSP;
380c2c66affSColin Finck }
381c2c66affSColin Finck 
382c2c66affSColin Finck void SelectionModel::DrawFramePoly(HDC hDCImage)
383c2c66affSColin Finck {
384aac89519SKatayama Hirofumi MZ     /* draw the freehand selection inverted/xored */
385aac89519SKatayama Hirofumi MZ     Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE);
386c2c66affSColin Finck }
387c2c66affSColin Finck 
388aac89519SKatayama Hirofumi MZ void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
389c2c66affSColin Finck {
390aac89519SKatayama Hirofumi MZ     m_rc.left = min(ptFrom.x, ptTo.x);
391aac89519SKatayama Hirofumi MZ     m_rc.top = min(ptFrom.y, ptTo.y);
392aac89519SKatayama Hirofumi MZ     m_rc.right = max(ptFrom.x, ptTo.x);
393aac89519SKatayama Hirofumi MZ     m_rc.bottom = max(ptFrom.y, ptTo.y);
394c2c66affSColin Finck }
395c2c66affSColin Finck 
396aac89519SKatayama Hirofumi MZ void SelectionModel::Dragging(CANVAS_HITTEST hit, POINT pt)
397c2c66affSColin Finck {
398aac89519SKatayama Hirofumi MZ     switch (hit)
399c2c66affSColin Finck     {
400aac89519SKatayama Hirofumi MZ         case HIT_NONE:
401c2c66affSColin Finck             break;
402aac89519SKatayama Hirofumi MZ         case HIT_UPPER_LEFT:
403aac89519SKatayama Hirofumi MZ             m_rc.left += pt.x - m_ptHit.x;
404aac89519SKatayama Hirofumi MZ             m_rc.top += pt.y - m_ptHit.y;
405c2c66affSColin Finck             break;
406aac89519SKatayama Hirofumi MZ         case HIT_UPPER_CENTER:
407aac89519SKatayama Hirofumi MZ             m_rc.top += pt.y - m_ptHit.y;
408c2c66affSColin Finck             break;
409aac89519SKatayama Hirofumi MZ         case HIT_UPPER_RIGHT:
410aac89519SKatayama Hirofumi MZ             m_rc.right += pt.x - m_ptHit.x;
411aac89519SKatayama Hirofumi MZ             m_rc.top += pt.y - m_ptHit.y;
412c2c66affSColin Finck             break;
413aac89519SKatayama Hirofumi MZ         case HIT_MIDDLE_LEFT:
414aac89519SKatayama Hirofumi MZ             m_rc.left += pt.x - m_ptHit.x;
415c2c66affSColin Finck             break;
416aac89519SKatayama Hirofumi MZ         case HIT_MIDDLE_RIGHT:
417aac89519SKatayama Hirofumi MZ             m_rc.right += pt.x - m_ptHit.x;
418c2c66affSColin Finck             break;
419aac89519SKatayama Hirofumi MZ         case HIT_LOWER_LEFT:
420aac89519SKatayama Hirofumi MZ             m_rc.left += pt.x - m_ptHit.x;
421aac89519SKatayama Hirofumi MZ             m_rc.bottom += pt.y - m_ptHit.y;
422c2c66affSColin Finck             break;
423aac89519SKatayama Hirofumi MZ         case HIT_LOWER_CENTER:
424aac89519SKatayama Hirofumi MZ             m_rc.bottom += pt.y - m_ptHit.y;
425c2c66affSColin Finck             break;
426aac89519SKatayama Hirofumi MZ         case HIT_LOWER_RIGHT:
427aac89519SKatayama Hirofumi MZ             m_rc.right += pt.x - m_ptHit.x;
428aac89519SKatayama Hirofumi MZ             m_rc.bottom += pt.y - m_ptHit.y;
429aac89519SKatayama Hirofumi MZ             break;
430aac89519SKatayama Hirofumi MZ         case HIT_BORDER:
431aac89519SKatayama Hirofumi MZ         case HIT_INNER:
432aac89519SKatayama Hirofumi MZ             OffsetRect(&m_rc, pt.x - m_ptHit.x, pt.y - m_ptHit.y);
433c2c66affSColin Finck             break;
434c2c66affSColin Finck     }
435aac89519SKatayama Hirofumi MZ     m_ptHit = pt;
436c2c66affSColin Finck }
437c2c66affSColin Finck 
438aac89519SKatayama Hirofumi MZ void SelectionModel::ClearMask()
439361a2ce4SKatayama Hirofumi MZ {
440aac89519SKatayama Hirofumi MZ     if (m_hbmMask)
441aac89519SKatayama Hirofumi MZ     {
442aac89519SKatayama Hirofumi MZ         ::DeleteObject(m_hbmMask);
443aac89519SKatayama Hirofumi MZ         m_hbmMask = NULL;
444aac89519SKatayama Hirofumi MZ     }
445aac89519SKatayama Hirofumi MZ }
446aac89519SKatayama Hirofumi MZ 
447aac89519SKatayama Hirofumi MZ void SelectionModel::ClearColor()
448aac89519SKatayama Hirofumi MZ {
449aac89519SKatayama Hirofumi MZ     if (m_hbmColor)
450aac89519SKatayama Hirofumi MZ     {
451aac89519SKatayama Hirofumi MZ         ::DeleteObject(m_hbmColor);
452aac89519SKatayama Hirofumi MZ         m_hbmColor = NULL;
453aac89519SKatayama Hirofumi MZ     }
454aac89519SKatayama Hirofumi MZ }
455aac89519SKatayama Hirofumi MZ 
456e8c7e300SKatayama Hirofumi MZ void SelectionModel::HideSelection()
457e8c7e300SKatayama Hirofumi MZ {
4587aadc1e1SKatayama Hirofumi MZ     m_bShow = m_bContentChanged = FALSE;
459e8c7e300SKatayama Hirofumi MZ     ClearColor();
460e8c7e300SKatayama Hirofumi MZ     ClearMask();
461e8c7e300SKatayama Hirofumi MZ     ::SetRectEmpty(&m_rc);
462e8c7e300SKatayama Hirofumi MZ     ::SetRectEmpty(&m_rcOld);
463e8c7e300SKatayama Hirofumi MZ     imageModel.NotifyImageChanged();
464e8c7e300SKatayama Hirofumi MZ }
465e8c7e300SKatayama Hirofumi MZ 
466e8c7e300SKatayama Hirofumi MZ void SelectionModel::DeleteSelection()
467aac89519SKatayama Hirofumi MZ {
468aac89519SKatayama Hirofumi MZ     if (!m_bShow)
469aac89519SKatayama Hirofumi MZ         return;
470aac89519SKatayama Hirofumi MZ 
471e8c7e300SKatayama Hirofumi MZ     TakeOff();
472e8c7e300SKatayama Hirofumi MZ     imageModel.PushImageForUndo();
4737aadc1e1SKatayama Hirofumi MZ     DrawBackground(imageModel.GetDC());
474e8c7e300SKatayama Hirofumi MZ 
475e8c7e300SKatayama Hirofumi MZ     HideSelection();
476361a2ce4SKatayama Hirofumi MZ }
4777aadc1e1SKatayama Hirofumi MZ 
4787aadc1e1SKatayama Hirofumi MZ void SelectionModel::InvertSelection()
4797aadc1e1SKatayama Hirofumi MZ {
4807aadc1e1SKatayama Hirofumi MZ     TakeOff();
4817aadc1e1SKatayama Hirofumi MZ 
4827aadc1e1SKatayama Hirofumi MZ     BITMAP bm;
4837aadc1e1SKatayama Hirofumi MZ     ::GetObject(m_hbmColor, sizeof(bm), &bm);
4847aadc1e1SKatayama Hirofumi MZ 
4857aadc1e1SKatayama Hirofumi MZ     HDC hdc = ::CreateCompatibleDC(NULL);
4867aadc1e1SKatayama Hirofumi MZ     HGDIOBJ hbmOld = ::SelectObject(hdc, m_hbmColor);
4877aadc1e1SKatayama Hirofumi MZ     RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight };
4887aadc1e1SKatayama Hirofumi MZ     ::InvertRect(hdc, &rc);
4897aadc1e1SKatayama Hirofumi MZ     ::SelectObject(hdc, hbmOld);
4907aadc1e1SKatayama Hirofumi MZ     ::DeleteDC(hdc);
4917aadc1e1SKatayama Hirofumi MZ 
4927aadc1e1SKatayama Hirofumi MZ     NotifyContentChanged();
4937aadc1e1SKatayama Hirofumi MZ }
4947aadc1e1SKatayama Hirofumi MZ 
4957aadc1e1SKatayama Hirofumi MZ void SelectionModel::NotifyContentChanged()
4967aadc1e1SKatayama Hirofumi MZ {
4977aadc1e1SKatayama Hirofumi MZ     m_bContentChanged = TRUE;
4987aadc1e1SKatayama Hirofumi MZ     imageModel.NotifyImageChanged();
4997aadc1e1SKatayama Hirofumi MZ }
5007aadc1e1SKatayama Hirofumi MZ 
5017aadc1e1SKatayama Hirofumi MZ void SelectionModel::SwapWidthAndHeight()
5027aadc1e1SKatayama Hirofumi MZ {
5037aadc1e1SKatayama Hirofumi MZ     INT cx = m_rc.Width();
5047aadc1e1SKatayama Hirofumi MZ     INT cy = m_rc.Height();
5057aadc1e1SKatayama Hirofumi MZ     m_rc.right = m_rc.left + cy;
5067aadc1e1SKatayama Hirofumi MZ     m_rc.bottom = m_rc.top + cx;
5077aadc1e1SKatayama Hirofumi MZ }
508