selectionmodel.cpp (29e147be) selectionmodel.cpp (aac89519)
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/selectionmodel.cpp
5 * PURPOSE: Keep track of selection parameters, notify listeners
6 * PROGRAMMERS: Benedikt Freisen
7 * Katayama Hirofumi MZ
8 */
9
10#include "precomp.h"
11
12SelectionModel selectionModel;
13
14/* FUNCTIONS ********************************************************/
15
16SelectionModel::SelectionModel()
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/selectionmodel.cpp
5 * PURPOSE: Keep track of selection parameters, notify listeners
6 * PROGRAMMERS: Benedikt Freisen
7 * Katayama Hirofumi MZ
8 */
9
10#include "precomp.h"
11
12SelectionModel selectionModel;
13
14/* FUNCTIONS ********************************************************/
15
16SelectionModel::SelectionModel()
17 : m_hDC(CreateCompatibleDC(NULL))
18 , m_hBm(NULL)
19 , m_hMask(NULL)
17 : m_hbmColor(NULL)
18 , m_hbmMask(NULL)
20 , m_ptStack(NULL)
21 , m_iPtSP(0)
19 , m_ptStack(NULL)
20 , m_iPtSP(0)
21 , m_bShow(FALSE)
22{
22{
23 SetRectEmpty(&m_rcSrc);
24 SetRectEmpty(&m_rcDest);
23 ::SetRectEmpty(&m_rc);
24 m_ptHit.x = m_ptHit.y = -1;
25}
26
27SelectionModel::~SelectionModel()
28{
25}
26
27SelectionModel::~SelectionModel()
28{
29 DeleteDC(m_hDC);
29 ClearColor();
30 ClearMask();
30 ResetPtStack();
31 ResetPtStack();
31 if (m_hBm)
32 {
33 DeleteObject(m_hBm);
34 }
35 if (m_hMask)
36 {
37 DeleteObject(m_hMask);
38 }
39}
40
41void SelectionModel::ResetPtStack()
42{
32}
33
34void SelectionModel::ResetPtStack()
35{
43 if (m_ptStack != NULL)
44 HeapFree(GetProcessHeap(), 0, m_ptStack);
45 m_ptStack = NULL;
36 if (m_ptStack)
37 {
38 free(m_ptStack);
39 m_ptStack = NULL;
40 }
46 m_iPtSP = 0;
47}
48
41 m_iPtSP = 0;
42}
43
49void SelectionModel::PushToPtStack(LONG x, LONG y)
44void SelectionModel::PushToPtStack(POINT pt)
50{
45{
51 if (m_iPtSP % 1024 == 0)
46#define GROW_COUNT 256
47 if (m_iPtSP % GROW_COUNT == 0)
52 {
48 {
53 if (m_ptStack)
54 m_ptStack = (POINT*) HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, m_ptStack, sizeof(POINT) * (m_iPtSP + 1024));
55 else
56 m_ptStack = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
49 INT nNewCount = m_iPtSP + GROW_COUNT;
50 LPPOINT pptNew = (LPPOINT)realloc(m_ptStack, sizeof(POINT) * nNewCount);
51 if (pptNew == NULL)
52 return;
53 m_ptStack = pptNew;
57 }
54 }
58 m_ptStack[m_iPtSP].x = x;
59 m_ptStack[m_iPtSP].y = y;
55 m_ptStack[m_iPtSP] = pt;
60 m_iPtSP++;
56 m_iPtSP++;
57#undef GROW_COUNT
61}
62
58}
59
63void SelectionModel::CalculateBoundingBoxAndContents(HDC hDCImage)
60void SelectionModel::ShiftPtStack(BOOL bPlus)
64{
61{
65 int i;
66 m_rcSrc.left = m_rcSrc.top = MAXLONG;
67 m_rcSrc.right = m_rcSrc.bottom = 0;
68 for (i = 0; i < m_iPtSP; i++)
62 if (bPlus)
69 {
63 {
70 if (m_ptStack[i].x < m_rcSrc.left)
71 m_rcSrc.left = m_ptStack[i].x;
72 if (m_ptStack[i].y < m_rcSrc.top)
73 m_rcSrc.top = m_ptStack[i].y;
74 if (m_ptStack[i].x > m_rcSrc.right)
75 m_rcSrc.right = m_ptStack[i].x;
76 if (m_ptStack[i].y > m_rcSrc.bottom)
77 m_rcSrc.bottom = m_ptStack[i].y;
64 for (INT i = 0; i < m_iPtSP; ++i)
65 {
66 POINT& pt = m_ptStack[i];
67 pt.x += m_rc.left;
68 pt.y += m_rc.top;
69 }
78 }
70 }
79 m_rcSrc.right += 1;
80 m_rcSrc.bottom += 1;
81 m_rcDest.left = m_rcSrc.left;
82 m_rcDest.top = m_rcSrc.top;
83 m_rcDest.right = m_rcSrc.right;
84 m_rcDest.bottom = m_rcSrc.bottom;
85
86 if (m_iPtSP > 1)
71 else
87 {
72 {
88 DeleteObject(m_hMask);
89 m_hMask = CreateBitmap(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 1, 1, NULL);
90 DeleteObject(SelectObject(m_hDC, m_hMask));
91 POINT *m_ptStackCopy = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * m_iPtSP);
92 for (i = 0; i < m_iPtSP; i++)
73 for (INT i = 0; i < m_iPtSP; ++i)
93 {
74 {
94 m_ptStackCopy[i].x = m_ptStack[i].x - m_rcSrc.left;
95 m_ptStackCopy[i].y = m_ptStack[i].y - m_rcSrc.top;
75 POINT& pt = m_ptStack[i];
76 pt.x -= m_rc.left;
77 pt.y -= m_rc.top;
96 }
78 }
97 Poly(m_hDC, m_ptStackCopy, m_iPtSP, 0x00ffffff, 0x00ffffff, 1, 2, TRUE, FALSE);
98 HeapFree(GetProcessHeap(), 0, m_ptStackCopy);
99 SelectObject(m_hDC, m_hBm = CreateDIBWithProperties(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc)));
100 imageModel.ResetToPrevious();
101 MaskBlt(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), hDCImage, m_rcSrc.left,
102 m_rcSrc.top, m_hMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
103 }
104}
105
79 }
80}
81
106void SelectionModel::CalculateContents(HDC hDCImage)
82void SelectionModel::BuildMaskFromPtStack()
107{
83{
108 DeleteObject(m_hMask);
109 m_hMask = CreateBitmap(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 1, 1, NULL);
110 DeleteObject(SelectObject(m_hDC, m_hMask));
111 Rect(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 0x00ffffff, 0x00ffffff, 1, 2);
112 SelectObject(m_hDC, m_hBm = CreateDIBWithProperties(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc)));
113 BitBlt(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), hDCImage, m_rcSrc.left,
114 m_rcSrc.top, SRCCOPY);
84 CRect rc = { MAXLONG, MAXLONG, 0, 0 };
85 for (INT i = 0; i < m_iPtSP; ++i)
86 {
87 POINT& pt = m_ptStack[i];
88 rc.left = min(pt.x, rc.left);
89 rc.top = min(pt.y, rc.top);
90 rc.right = max(pt.x, rc.right);
91 rc.bottom = max(pt.y, rc.bottom);
92 }
93 rc.right += 1;
94 rc.bottom += 1;
95
96 m_rc = rc;
97
98 ShiftPtStack(FALSE);
99
100 ClearMask();
101
102 HDC hdcMem = ::CreateCompatibleDC(NULL);
103 m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
104 HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
105 FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
106 HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
107 HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
108 ::Polygon(hdcMem, m_ptStack, m_iPtSP);
109 ::SelectObject(hdcMem, hbrOld);
110 ::SelectObject(hdcMem, hPenOld);
111 ::SelectObject(hdcMem, hbmOld);
112 ::DeleteDC(hdcMem);
115}
116
117void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
118{
113}
114
115void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
116{
119 Poly(hDCImage, m_ptStack, m_iPtSP, crBg, crBg, 1, 2, TRUE, FALSE);
117 ShiftPtStack(TRUE);
118
119 HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN));
120 HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg));
121 ::Polygon(hDCImage, m_ptStack, m_iPtSP);
122 ::DeleteObject(::SelectObject(hDCImage, hbrOld));
123 ::SelectObject(hDCImage, hPenOld);
124
125 ShiftPtStack(FALSE);
120}
121
122void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
123{
126}
127
128void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
129{
124 Rect(hDCImage, m_rcSrc.left, m_rcSrc.top, m_rcSrc.right, m_rcSrc.bottom, crBg, crBg, 0, 1);
130 Rect(hDCImage, m_rc.left, m_rc.top, m_rc.right, m_rc.bottom, crBg, crBg, 0, 1);
125}
126
131}
132
127void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
133void SelectionModel::DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg, BOOL bBgTransparent)
128{
134{
129 if (!bBgTransparent)
130 MaskBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest),
131 m_hDC, 0, 0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
132 else
133 ColorKeyedMaskBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest),
134 m_hDC, 0, 0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND), crBg);
135 CRect rc = *prc;
136 if (::IsRectEmpty(&rc))
137 return;
138
139 BITMAP bm;
140 GetObject(m_hbmColor, sizeof(BITMAP), &bm);
141
142 COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
143
144 HDC hMemDC = CreateCompatibleDC(hDCImage);
145 HGDIOBJ hbmOld = SelectObject(hMemDC, m_hbmColor);
146 ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(),
147 hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor);
148 SelectObject(hMemDC, hbmOld);
149 DeleteDC(hMemDC);
135}
136
150}
151
137void SelectionModel::DrawSelectionStretched(HDC hDCImage)
152void SelectionModel::GetSelectionContents(HDC hDCImage)
138{
153{
139 StretchBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0, GetDIBWidth(m_hBm), GetDIBHeight(m_hBm), SRCCOPY);
154 ClearColor();
155
156 HDC hMemDC = ::CreateCompatibleDC(NULL);
157 m_hbmColor = CreateColorDIB(m_rc.Width(), m_rc.Height(), RGB(255, 255, 255));
158 HGDIOBJ hbmOld = ::SelectObject(hMemDC, m_hbmColor);
159 ::BitBlt(hMemDC, 0, 0, m_rc.Width(), m_rc.Height(), hDCImage, m_rc.left, m_rc.top, SRCCOPY);
160 ::SelectObject(hMemDC, hbmOld);
161 ::DeleteDC(hMemDC);
140}
141
162}
163
142void SelectionModel::ScaleContentsToFit()
164BOOL SelectionModel::TakeOff()
143{
165{
144 HDC hTempDC;
145 HBITMAP hTempBm;
146 hTempDC = CreateCompatibleDC(m_hDC);
147 hTempBm = CreateDIBWithProperties(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest));
148 SelectObject(hTempDC, hTempBm);
149 SelectObject(m_hDC, m_hBm);
150 StretchBlt(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0,
151 GetDIBWidth(m_hBm), GetDIBHeight(m_hBm), SRCCOPY);
152 DeleteObject(m_hBm);
153 m_hBm = hTempBm;
154 hTempBm = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
155 SelectObject(hTempDC, hTempBm);
156 SelectObject(m_hDC, m_hMask);
157 StretchBlt(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0,
158 GetDIBWidth(m_hMask), GetDIBHeight(m_hMask), SRCCOPY);
159 DeleteObject(m_hMask);
160 m_hMask = hTempBm;
161 SelectObject(m_hDC, m_hBm);
162 DeleteDC(hTempDC);
166 if (m_hbmColor || ::IsRectEmpty(&m_rc))
167 return FALSE;
168
169 HDC hDCImage = imageModel.GetDC();
170 GetSelectionContents(hDCImage);
171
172 if (toolsModel.GetActiveTool() == TOOL_FREESEL)
173 {
174 DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
175 }
176 else
177 {
178 ClearMask();
179 DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
180 }
181
182 imageArea.Invalidate(FALSE);
183 return TRUE;
163}
164
184}
185
165void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
186void SelectionModel::Landing()
166{
187{
167 HDC hTempDC;
168 HBITMAP hTempMask;
188 if (!m_hbmColor)
189 return;
169
190
170 m_hBm = CopyDIBImage(hBm);
171 DeleteObject(SelectObject(m_hDC, m_hBm));
191 DrawSelection(imageModel.GetDC(), &m_rc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
172
192
173 SetRectEmpty(&m_rcSrc);
174 m_rcDest.left = x;
175 m_rcDest.top = y;
176 m_rcDest.right = m_rcDest.left + GetDIBWidth(m_hBm);
177 m_rcDest.bottom = m_rcDest.top + GetDIBHeight(m_hBm);
193 ::SetRectEmpty(&m_rc);
194 ClearMask();
195 ClearColor();
178
196
179 hTempDC = CreateCompatibleDC(m_hDC);
180 hTempMask = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
181 SelectObject(hTempDC, hTempMask);
182 Rect(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 0x00ffffff, 0x00ffffff, 1, 1);
183 DeleteObject(m_hMask);
184 m_hMask = hTempMask;
185 DeleteDC(hTempDC);
197 imageModel.CopyPrevious();
186}
187
198}
199
200void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
201{
202 m_hbmColor = CopyDIBImage(hBm);
203 ::DeleteObject(m_hbmColor);
204
205 m_rc.left = x;
206 m_rc.top = y;
207 m_rc.right = m_rc.left + GetDIBWidth(hBm);
208 m_rc.bottom = m_rc.top + GetDIBHeight(hBm);
209
210 ClearMask();
211}
212
188void SelectionModel::FlipHorizontally()
189{
213void SelectionModel::FlipHorizontally()
214{
190 SelectObject(m_hDC, m_hMask);
191 StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, 0, -RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC,
192 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
193 SelectObject(m_hDC, m_hBm);
194 StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, 0, -RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC,
195 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
215 TakeOff();
216
217 HDC hdcMem = ::CreateCompatibleDC(NULL);
218 if (m_hbmMask)
219 {
220 ::SelectObject(hdcMem, m_hbmMask);
221 ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
222 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
223 }
224 if (m_hbmColor)
225 {
226 ::SelectObject(hdcMem, m_hbmColor);
227 ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
228 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
229 }
230 ::DeleteDC(hdcMem);
231
196 NotifyRefreshNeeded();
197}
198
199void SelectionModel::FlipVertically()
200{
232 NotifyRefreshNeeded();
233}
234
235void SelectionModel::FlipVertically()
236{
201 SelectObject(m_hDC, m_hMask);
202 StretchBlt(m_hDC, 0, RECT_HEIGHT(m_rcDest) - 1, RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
203 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
204 SelectObject(m_hDC, m_hBm);
205 StretchBlt(m_hDC, 0, RECT_HEIGHT(m_rcDest) - 1, RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
206 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
237 TakeOff();
238
239 HDC hdcMem = ::CreateCompatibleDC(NULL);
240 if (m_hbmMask)
241 {
242 ::SelectObject(hdcMem, m_hbmMask);
243 ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
244 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
245 }
246 if (m_hbmColor)
247 {
248 ::SelectObject(hdcMem, m_hbmColor);
249 ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
250 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
251 }
252 ::DeleteDC(hdcMem);
253
207 NotifyRefreshNeeded();
208}
209
210void SelectionModel::RotateNTimes90Degrees(int iN)
211{
212 HBITMAP hbm;
254 NotifyRefreshNeeded();
255}
256
257void SelectionModel::RotateNTimes90Degrees(int iN)
258{
259 HBITMAP hbm;
260 HGDIOBJ hbmOld;
261 HDC hdcMem = ::CreateCompatibleDC(NULL);
262
213 switch (iN)
214 {
263 switch (iN)
264 {
215 case 1:
216 case 3:
217 imageModel.DeleteSelection();
218 imageModel.CopyPrevious();
219 SelectObject(m_hDC, m_hBm);
220 hbm = Rotate90DegreeBlt(m_hDC, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), iN == 1);
221 InsertFromHBITMAP(hbm, m_rcDest.left, m_rcDest.top);
222 DeleteObject(hbm);
223 selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
224 selectionWindow.ForceRefreshSelectionContents();
225 placeSelWin();
226 break;
227 case 2:
228 SelectObject(m_hDC, m_hMask);
229 StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
230 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
231 SelectObject(m_hDC, m_hBm);
232 StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
233 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
234 break;
265 case 1:
266 case 3:
267 TakeOff();
268 if (m_hbmColor)
269 {
270 hbmOld = ::SelectObject(hdcMem, m_hbmColor);
271 hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, FALSE);
272 ::SelectObject(hdcMem, hbmOld);
273 ::DeleteObject(m_hbmColor);
274 m_hbmColor = hbm;
275 }
276 if (m_hbmMask)
277 {
278 hbmOld = ::SelectObject(hdcMem, m_hbmMask);
279 hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, TRUE);
280 ::SelectObject(hdcMem, hbmOld);
281 ::DeleteObject(m_hbmMask);
282 m_hbmMask = hbm;
283 }
284 break;
285
286 case 2:
287 TakeOff();
288 if (m_hbmColor)
289 {
290 hbmOld = ::SelectObject(hdcMem, m_hbmColor);
291 ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
292 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
293 ::SelectObject(hdcMem, hbmOld);
294 }
295 if (m_hbmMask)
296 {
297 hbmOld = ::SelectObject(hdcMem, m_hbmMask);
298 ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
299 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
300 ::SelectObject(hdcMem, hbmOld);
301 }
302 break;
235 }
303 }
304
305 ::DeleteDC(hdcMem);
236 NotifyRefreshNeeded();
237}
238
239void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
240{
241 if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
242 return;
243
306 NotifyRefreshNeeded();
307}
308
309void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
310{
311 if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
312 return;
313
244 imageModel.DeleteSelection();
245 imageModel.CopyPrevious();
314 TakeOff();
246
315
247 INT oldWidth = RECT_WIDTH(m_rcDest);
248 INT oldHeight = RECT_HEIGHT(m_rcDest);
316 INT oldWidth = m_rc.Width();
317 INT oldHeight = m_rc.Height();
249 INT newWidth = oldWidth * nStretchPercentX / 100;
250 INT newHeight = oldHeight * nStretchPercentY / 100;
251
252 if (oldWidth != newWidth || oldHeight != newHeight)
253 {
318 INT newWidth = oldWidth * nStretchPercentX / 100;
319 INT newHeight = oldHeight * nStretchPercentY / 100;
320
321 if (oldWidth != newWidth || oldHeight != newHeight)
322 {
254 SelectObject(m_hDC, m_hBm);
255 HBITMAP hbm0 = CopyDIBImage(m_hBm, newWidth, newHeight);
256 InsertFromHBITMAP(hbm0, m_rcDest.left, m_rcDest.top);
257 DeleteObject(hbm0);
323 HBITMAP hbm0 = CopyDIBImage(m_hbmColor, newWidth, newHeight);
324 InsertFromHBITMAP(hbm0, m_rc.left, m_rc.top);
325 ::DeleteObject(hbm0);
258 }
259
326 }
327
328 HDC hDC = ::CreateCompatibleDC(NULL);
329
260 if (nSkewDegX)
261 {
330 if (nSkewDegX)
331 {
262 SelectObject(m_hDC, m_hBm);
263 HBITMAP hbm1 = SkewDIB(m_hDC, m_hBm, nSkewDegX, FALSE);
264 InsertFromHBITMAP(hbm1, m_rcDest.left, m_rcDest.top);
265 DeleteObject(hbm1);
332 ::SelectObject(hDC, m_hbmColor);
333 HBITMAP hbm1 = SkewDIB(hDC, m_hbmColor, nSkewDegX, FALSE);
334 InsertFromHBITMAP(hbm1, m_rc.left, m_rc.top);
335 ::DeleteObject(hbm1);
266 }
267
268 if (nSkewDegY)
269 {
336 }
337
338 if (nSkewDegY)
339 {
270 SelectObject(m_hDC, m_hBm);
271 HBITMAP hbm2 = SkewDIB(m_hDC, m_hBm, nSkewDegY, TRUE);
272 InsertFromHBITMAP(hbm2, m_rcDest.left, m_rcDest.top);
273 DeleteObject(hbm2);
340 ::SelectObject(hDC, m_hbmColor);
341 HBITMAP hbm2 = SkewDIB(hDC, m_hbmColor, nSkewDegY, TRUE);
342 InsertFromHBITMAP(hbm2, m_rc.left, m_rc.top);
343 ::DeleteObject(hbm2);
274 }
275
344 }
345
276 selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
277 selectionWindow.ForceRefreshSelectionContents();
278 placeSelWin();
346 ::DeleteDC(hDC);
347
348 m_bShow = TRUE;
279 NotifyRefreshNeeded();
280}
281
282HBITMAP SelectionModel::GetBitmap() const
283{
349 NotifyRefreshNeeded();
350}
351
352HBITMAP SelectionModel::GetBitmap() const
353{
284 return m_hBm;
354 return m_hbmColor;
285}
286
287int SelectionModel::PtStackSize() const
288{
289 return m_iPtSP;
290}
291
292void SelectionModel::DrawFramePoly(HDC hDCImage)
293{
355}
356
357int SelectionModel::PtStackSize() const
358{
359 return m_iPtSP;
360}
361
362void SelectionModel::DrawFramePoly(HDC hDCImage)
363{
294 Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE); /* draw the freehand selection inverted/xored */
364 /* draw the freehand selection inverted/xored */
365 Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE);
295}
296
366}
367
297void SelectionModel::SetSrcAndDestRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
368void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
298{
369{
299 m_rcDest.left = m_rcSrc.left = min(ptFrom.x, ptTo.x);
300 m_rcDest.top = m_rcSrc.top = min(ptFrom.y, ptTo.y);
301 m_rcDest.right = m_rcSrc.right = max(ptFrom.x, ptTo.x);
302 m_rcDest.bottom = m_rcSrc.bottom = max(ptFrom.y, ptTo.y);
370 m_rc.left = min(ptFrom.x, ptTo.x);
371 m_rc.top = min(ptFrom.y, ptTo.y);
372 m_rc.right = max(ptFrom.x, ptTo.x);
373 m_rc.bottom = max(ptFrom.y, ptTo.y);
303}
304
374}
375
305void SelectionModel::SetSrcRectSizeToZero()
376void SelectionModel::Dragging(CANVAS_HITTEST hit, POINT pt)
306{
377{
307 m_rcSrc.right = m_rcSrc.left;
308 m_rcSrc.bottom = m_rcSrc.top;
309}
310
311BOOL SelectionModel::IsSrcRectSizeNonzero() const
312{
313 return (RECT_WIDTH(m_rcSrc) != 0) && (RECT_HEIGHT(m_rcSrc) != 0);
314}
315
316void SelectionModel::ModifyDestRect(POINT& ptDelta, int iAction)
317{
318 POINT ptDeltaUsed;
319
320 switch (iAction)
378 switch (hit)
321 {
379 {
322 case ACTION_MOVE: /* move selection */
323 ptDeltaUsed.x = ptDelta.x;
324 ptDeltaUsed.y = ptDelta.y;
325 OffsetRect(&m_rcDest, ptDeltaUsed.x, ptDeltaUsed.y);
380 case HIT_NONE:
326 break;
381 break;
327 case ACTION_RESIZE_TOP_LEFT: /* resize at upper left corner */
328 ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
329 ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
330 m_rcDest.left += ptDeltaUsed.x;
331 m_rcDest.top += ptDeltaUsed.y;
382 case HIT_UPPER_LEFT:
383 m_rc.left += pt.x - m_ptHit.x;
384 m_rc.top += pt.y - m_ptHit.y;
332 break;
385 break;
333 case ACTION_RESIZE_TOP: /* resize at top edge */
334 ptDeltaUsed.x = ptDelta.x;
335 ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
336 m_rcDest.top += ptDeltaUsed.y;
386 case HIT_UPPER_CENTER:
387 m_rc.top += pt.y - m_ptHit.y;
337 break;
388 break;
338 case ACTION_RESIZE_TOP_RIGHT: /* resize at upper right corner */
339 ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
340 ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
341 m_rcDest.top += ptDeltaUsed.y;
342 m_rcDest.right += ptDeltaUsed.x;
389 case HIT_UPPER_RIGHT:
390 m_rc.right += pt.x - m_ptHit.x;
391 m_rc.top += pt.y - m_ptHit.y;
343 break;
392 break;
344 case ACTION_RESIZE_LEFT: /* resize at left edge */
345 ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
346 ptDeltaUsed.y = ptDelta.y;
347 m_rcDest.left += ptDeltaUsed.x;
393 case HIT_MIDDLE_LEFT:
394 m_rc.left += pt.x - m_ptHit.x;
348 break;
395 break;
349 case ACTION_RESIZE_RIGHT: /* resize at right edge */
350 ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
351 ptDeltaUsed.y = ptDelta.y;
352 m_rcDest.right += ptDeltaUsed.x;
396 case HIT_MIDDLE_RIGHT:
397 m_rc.right += pt.x - m_ptHit.x;
353 break;
398 break;
354 case ACTION_RESIZE_BOTTOM_LEFT: /* resize at lower left corner */
355 ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
356 ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
357 m_rcDest.left += ptDeltaUsed.x;
358 m_rcDest.bottom += ptDeltaUsed.y;
399 case HIT_LOWER_LEFT:
400 m_rc.left += pt.x - m_ptHit.x;
401 m_rc.bottom += pt.y - m_ptHit.y;
359 break;
402 break;
360 case ACTION_RESIZE_BOTTOM: /* resize at bottom edge */
361 ptDeltaUsed.x = ptDelta.x;
362 ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
363 m_rcDest.bottom += ptDeltaUsed.y;
403 case HIT_LOWER_CENTER:
404 m_rc.bottom += pt.y - m_ptHit.y;
364 break;
405 break;
365 case ACTION_RESIZE_BOTTOM_RIGHT: /* resize at lower right corner */
366 ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
367 ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
368 m_rcDest.right += ptDeltaUsed.x;
369 m_rcDest.bottom += ptDeltaUsed.y;
406 case HIT_LOWER_RIGHT:
407 m_rc.right += pt.x - m_ptHit.x;
408 m_rc.bottom += pt.y - m_ptHit.y;
370 break;
409 break;
410 case HIT_BORDER:
411 case HIT_INNER:
412 OffsetRect(&m_rc, pt.x - m_ptHit.x, pt.y - m_ptHit.y);
413 break;
371 }
414 }
372 ptDelta.x -= ptDeltaUsed.x;
373 ptDelta.y -= ptDeltaUsed.y;
415 m_ptHit = pt;
374}
375
416}
417
376LONG SelectionModel::GetDestRectWidth() const
418void SelectionModel::NotifyRefreshNeeded()
377{
419{
378 return m_rcDest.right - m_rcDest.left;
420 imageArea.Invalidate(FALSE);
379}
380
421}
422
381LONG SelectionModel::GetDestRectHeight() const
423void SelectionModel::ClearMask()
382{
424{
383 return m_rcDest.bottom - m_rcDest.top;
425 if (m_hbmMask)
426 {
427 ::DeleteObject(m_hbmMask);
428 m_hbmMask = NULL;
429 }
384}
385
430}
431
386LONG SelectionModel::GetDestRectLeft() const
432void SelectionModel::ClearColor()
387{
433{
388 return m_rcDest.left;
434 if (m_hbmColor)
435 {
436 ::DeleteObject(m_hbmColor);
437 m_hbmColor = NULL;
438 }
389}
390
439}
440
391LONG SelectionModel::GetDestRectTop() const
441void SelectionModel::CancelSelection()
392{
442{
393 return m_rcDest.top;
394}
443 if (!m_bShow)
444 return;
395
445
396void SelectionModel::NotifyRefreshNeeded()
397{
398 selectionWindow.SendMessage(WM_SELECTIONMODELREFRESHNEEDED);
399}
446 imageModel.CopyPrevious();
447 if (m_bShow)
448 imageModel.Undo(TRUE);
400
449
401void SelectionModel::GetRect(LPRECT prc) const
402{
403 *prc = m_rcDest;
450 m_bShow = FALSE;
451 imageArea.Invalidate(FALSE);
404}
452}