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}
|