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 15c2c66affSColin Finck SelectionModel::SelectionModel() 16aac89519SKatayama Hirofumi MZ : m_hbmColor(NULL) 17aac89519SKatayama Hirofumi MZ , m_hbmMask(NULL) 183fa95ab9SKatayama Hirofumi MZ , m_ptStack(NULL) 193fa95ab9SKatayama Hirofumi MZ , m_iPtSP(0) 2017bdf554SKatayama Hirofumi MZ , m_rgbBack(RGB(255, 255, 255)) 21aac89519SKatayama Hirofumi MZ , m_bShow(FALSE) 227aadc1e1SKatayama Hirofumi MZ , m_bContentChanged(FALSE) 23c2c66affSColin Finck { 24aac89519SKatayama Hirofumi MZ ::SetRectEmpty(&m_rc); 25e8c7e300SKatayama Hirofumi MZ ::SetRectEmpty(&m_rcOld); 26aac89519SKatayama Hirofumi MZ m_ptHit.x = m_ptHit.y = -1; 273fa95ab9SKatayama Hirofumi MZ } 28c2c66affSColin Finck 293fa95ab9SKatayama Hirofumi MZ SelectionModel::~SelectionModel() 303fa95ab9SKatayama Hirofumi MZ { 31*ed9973f8SKatayama Hirofumi MZ ClearColorImage(); 32*ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 333fa95ab9SKatayama Hirofumi MZ ResetPtStack(); 34c2c66affSColin Finck } 35c2c66affSColin Finck 36c2c66affSColin Finck void SelectionModel::ResetPtStack() 37c2c66affSColin Finck { 38aac89519SKatayama Hirofumi MZ if (m_ptStack) 39aac89519SKatayama Hirofumi MZ { 40aac89519SKatayama Hirofumi MZ free(m_ptStack); 41c2c66affSColin Finck m_ptStack = NULL; 42aac89519SKatayama Hirofumi MZ } 43c2c66affSColin Finck m_iPtSP = 0; 44c2c66affSColin Finck } 45c2c66affSColin Finck 46aac89519SKatayama Hirofumi MZ void SelectionModel::PushToPtStack(POINT pt) 47c2c66affSColin Finck { 48aac89519SKatayama Hirofumi MZ #define GROW_COUNT 256 49aac89519SKatayama Hirofumi MZ if (m_iPtSP % GROW_COUNT == 0) 50c2c66affSColin Finck { 51aac89519SKatayama Hirofumi MZ INT nNewCount = m_iPtSP + GROW_COUNT; 52aac89519SKatayama Hirofumi MZ LPPOINT pptNew = (LPPOINT)realloc(m_ptStack, sizeof(POINT) * nNewCount); 53aac89519SKatayama Hirofumi MZ if (pptNew == NULL) 54aac89519SKatayama Hirofumi MZ return; 55aac89519SKatayama Hirofumi MZ m_ptStack = pptNew; 56c2c66affSColin Finck } 57aac89519SKatayama Hirofumi MZ m_ptStack[m_iPtSP] = pt; 58c2c66affSColin Finck m_iPtSP++; 59aac89519SKatayama Hirofumi MZ #undef GROW_COUNT 60c2c66affSColin Finck } 61c2c66affSColin Finck 62e8c7e300SKatayama Hirofumi MZ void SelectionModel::ShiftPtStack(INT dx, INT dy) 63c2c66affSColin Finck { 64aac89519SKatayama Hirofumi MZ for (INT i = 0; i < m_iPtSP; ++i) 65aac89519SKatayama Hirofumi MZ { 66aac89519SKatayama Hirofumi MZ POINT& pt = m_ptStack[i]; 67e8c7e300SKatayama Hirofumi MZ pt.x += dx; 68e8c7e300SKatayama Hirofumi MZ pt.y += dy; 69c2c66affSColin Finck } 70c2c66affSColin Finck } 71c2c66affSColin Finck 72aac89519SKatayama Hirofumi MZ void SelectionModel::BuildMaskFromPtStack() 73c2c66affSColin Finck { 74aac89519SKatayama Hirofumi MZ CRect rc = { MAXLONG, MAXLONG, 0, 0 }; 75aac89519SKatayama Hirofumi MZ for (INT i = 0; i < m_iPtSP; ++i) 76aac89519SKatayama Hirofumi MZ { 77aac89519SKatayama Hirofumi MZ POINT& pt = m_ptStack[i]; 78aac89519SKatayama Hirofumi MZ rc.left = min(pt.x, rc.left); 79aac89519SKatayama Hirofumi MZ rc.top = min(pt.y, rc.top); 80aac89519SKatayama Hirofumi MZ rc.right = max(pt.x, rc.right); 81aac89519SKatayama Hirofumi MZ rc.bottom = max(pt.y, rc.bottom); 82aac89519SKatayama Hirofumi MZ } 83aac89519SKatayama Hirofumi MZ rc.right += 1; 84aac89519SKatayama Hirofumi MZ rc.bottom += 1; 85aac89519SKatayama Hirofumi MZ 86e8c7e300SKatayama Hirofumi MZ m_rc = m_rcOld = rc; 87aac89519SKatayama Hirofumi MZ 88*ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 89aac89519SKatayama Hirofumi MZ 90e8c7e300SKatayama Hirofumi MZ ShiftPtStack(-m_rcOld.left, -m_rcOld.top); 91e8c7e300SKatayama Hirofumi MZ 92aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 93aac89519SKatayama Hirofumi MZ m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL); 94aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask); 95e8c7e300SKatayama Hirofumi MZ ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH)); 96aac89519SKatayama Hirofumi MZ HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN)); 97aac89519SKatayama Hirofumi MZ HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH)); 98aac89519SKatayama Hirofumi MZ ::Polygon(hdcMem, m_ptStack, m_iPtSP); 99aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbrOld); 100aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hPenOld); 101aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 102aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 103e8c7e300SKatayama Hirofumi MZ 104e8c7e300SKatayama Hirofumi MZ ShiftPtStack(+m_rcOld.left, +m_rcOld.top); 105c2c66affSColin Finck } 106c2c66affSColin Finck 107c2c66affSColin Finck void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg) 108c2c66affSColin Finck { 109e8c7e300SKatayama Hirofumi MZ if (::IsRectEmpty(&m_rcOld)) 110e8c7e300SKatayama Hirofumi MZ return; 111aac89519SKatayama Hirofumi MZ 112aac89519SKatayama Hirofumi MZ HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN)); 113aac89519SKatayama Hirofumi MZ HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg)); 114aac89519SKatayama Hirofumi MZ ::Polygon(hDCImage, m_ptStack, m_iPtSP); 115aac89519SKatayama Hirofumi MZ ::DeleteObject(::SelectObject(hDCImage, hbrOld)); 116aac89519SKatayama Hirofumi MZ ::SelectObject(hDCImage, hPenOld); 117c2c66affSColin Finck } 118c2c66affSColin Finck 119c2c66affSColin Finck void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg) 120c2c66affSColin Finck { 121e8c7e300SKatayama Hirofumi MZ if (::IsRectEmpty(&m_rcOld)) 122e8c7e300SKatayama Hirofumi MZ return; 123e8c7e300SKatayama Hirofumi MZ 124e8c7e300SKatayama Hirofumi MZ Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1); 125c2c66affSColin Finck } 126c2c66affSColin Finck 1277aadc1e1SKatayama Hirofumi MZ void SelectionModel::DrawBackground(HDC hDCImage) 1287aadc1e1SKatayama Hirofumi MZ { 1297aadc1e1SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_FREESEL) 1307aadc1e1SKatayama Hirofumi MZ DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor()); 1317aadc1e1SKatayama Hirofumi MZ else 1327aadc1e1SKatayama Hirofumi MZ DrawBackgroundRect(hDCImage, paletteModel.GetBgColor()); 1337aadc1e1SKatayama Hirofumi MZ } 1347aadc1e1SKatayama Hirofumi MZ 135e8c7e300SKatayama Hirofumi MZ void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent) 136c2c66affSColin Finck { 137e8c7e300SKatayama Hirofumi MZ CRect rc = m_rc; 138aac89519SKatayama Hirofumi MZ if (::IsRectEmpty(&rc)) 139aac89519SKatayama Hirofumi MZ return; 140aac89519SKatayama Hirofumi MZ 141aac89519SKatayama Hirofumi MZ BITMAP bm; 142e8c7e300SKatayama Hirofumi MZ if (!GetObject(m_hbmColor, sizeof(BITMAP), &bm)) 143e8c7e300SKatayama Hirofumi MZ return; 144aac89519SKatayama Hirofumi MZ 145aac89519SKatayama Hirofumi MZ COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID); 146aac89519SKatayama Hirofumi MZ 147aac89519SKatayama Hirofumi MZ HDC hMemDC = CreateCompatibleDC(hDCImage); 148aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld = SelectObject(hMemDC, m_hbmColor); 149aac89519SKatayama Hirofumi MZ ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(), 150aac89519SKatayama Hirofumi MZ hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor); 151aac89519SKatayama Hirofumi MZ SelectObject(hMemDC, hbmOld); 152aac89519SKatayama Hirofumi MZ DeleteDC(hMemDC); 153aac89519SKatayama Hirofumi MZ } 154aac89519SKatayama Hirofumi MZ 155aac89519SKatayama Hirofumi MZ void SelectionModel::GetSelectionContents(HDC hDCImage) 156aac89519SKatayama Hirofumi MZ { 157*ed9973f8SKatayama Hirofumi MZ ClearColorImage(); 158aac89519SKatayama Hirofumi MZ 159aac89519SKatayama Hirofumi MZ HDC hMemDC = ::CreateCompatibleDC(NULL); 160aac89519SKatayama Hirofumi MZ m_hbmColor = CreateColorDIB(m_rc.Width(), m_rc.Height(), RGB(255, 255, 255)); 161aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hMemDC, m_hbmColor); 162aac89519SKatayama Hirofumi MZ ::BitBlt(hMemDC, 0, 0, m_rc.Width(), m_rc.Height(), hDCImage, m_rc.left, m_rc.top, SRCCOPY); 163aac89519SKatayama Hirofumi MZ ::SelectObject(hMemDC, hbmOld); 164aac89519SKatayama Hirofumi MZ ::DeleteDC(hMemDC); 165aac89519SKatayama Hirofumi MZ } 166aac89519SKatayama Hirofumi MZ 167e8c7e300SKatayama Hirofumi MZ BOOL SelectionModel::IsLanded() const 168e8c7e300SKatayama Hirofumi MZ { 169e8c7e300SKatayama Hirofumi MZ return !m_hbmColor; 170e8c7e300SKatayama Hirofumi MZ } 171e8c7e300SKatayama Hirofumi MZ 172aac89519SKatayama Hirofumi MZ BOOL SelectionModel::TakeOff() 173aac89519SKatayama Hirofumi MZ { 174e8c7e300SKatayama Hirofumi MZ if (!IsLanded() || ::IsRectEmpty(&m_rc)) 175aac89519SKatayama Hirofumi MZ return FALSE; 176aac89519SKatayama Hirofumi MZ 177*ed9973f8SKatayama Hirofumi MZ // The background color is needed for transparency of selection 178e8c7e300SKatayama Hirofumi MZ m_rgbBack = paletteModel.GetBgColor(); 179*ed9973f8SKatayama Hirofumi MZ 180*ed9973f8SKatayama Hirofumi MZ // Get the contents of the selection area 181e8c7e300SKatayama Hirofumi MZ GetSelectionContents(imageModel.GetDC()); 182aac89519SKatayama Hirofumi MZ 183*ed9973f8SKatayama Hirofumi MZ // RectSel doesn't need the mask image 184e8c7e300SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_RECTSEL) 185*ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 186e8c7e300SKatayama Hirofumi MZ 187*ed9973f8SKatayama Hirofumi MZ // Save the selection area 188e8c7e300SKatayama Hirofumi MZ m_rcOld = m_rc; 189c2c66affSColin Finck 190bfd42c67SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 191aac89519SKatayama Hirofumi MZ return TRUE; 192c2c66affSColin Finck } 193c2c66affSColin Finck 194aac89519SKatayama Hirofumi MZ void SelectionModel::Landing() 195c2c66affSColin Finck { 196e8c7e300SKatayama Hirofumi MZ if (IsLanded() && !m_bShow) 197e8c7e300SKatayama Hirofumi MZ { 198e8c7e300SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 199aac89519SKatayama Hirofumi MZ return; 200e8c7e300SKatayama Hirofumi MZ } 201aac89519SKatayama Hirofumi MZ 202e8c7e300SKatayama Hirofumi MZ m_bShow = FALSE; 203aac89519SKatayama Hirofumi MZ 2047aadc1e1SKatayama Hirofumi MZ if (m_bContentChanged || 2057aadc1e1SKatayama Hirofumi MZ (!::EqualRect(m_rc, m_rcOld) && !::IsRectEmpty(m_rc) && !::IsRectEmpty(m_rcOld))) 206e8c7e300SKatayama Hirofumi MZ { 2072b623c1dSKatayama Hirofumi MZ imageModel.PushImageForUndo(); 208e8c7e300SKatayama Hirofumi MZ 209e8c7e300SKatayama Hirofumi MZ canvasWindow.m_drawing = FALSE; 210e8c7e300SKatayama Hirofumi MZ toolsModel.OnDrawOverlayOnImage(imageModel.GetDC()); 211e8c7e300SKatayama Hirofumi MZ } 212e8c7e300SKatayama Hirofumi MZ 213e8c7e300SKatayama Hirofumi MZ HideSelection(); 214c2c66affSColin Finck } 215c2c66affSColin Finck 2169afcbea2SKatayama Hirofumi MZ void SelectionModel::InsertFromHBITMAP(HBITMAP hbmColor, INT x, INT y, HBITMAP hbmMask) 217c2c66affSColin Finck { 218aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor); 219b5335fb9SKatayama Hirofumi MZ m_hbmColor = hbmColor; 220c2c66affSColin Finck 221aac89519SKatayama Hirofumi MZ m_rc.left = x; 222aac89519SKatayama Hirofumi MZ m_rc.top = y; 2239afcbea2SKatayama Hirofumi MZ m_rc.right = x + GetDIBWidth(hbmColor); 2249afcbea2SKatayama Hirofumi MZ m_rc.bottom = y + GetDIBHeight(hbmColor); 2259afcbea2SKatayama Hirofumi MZ 2269afcbea2SKatayama Hirofumi MZ if (hbmMask) 2279afcbea2SKatayama Hirofumi MZ { 2289afcbea2SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask); 229b5335fb9SKatayama Hirofumi MZ m_hbmMask = hbmMask; 2309afcbea2SKatayama Hirofumi MZ } 2319afcbea2SKatayama Hirofumi MZ else 2329afcbea2SKatayama Hirofumi MZ { 233*ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 2349afcbea2SKatayama Hirofumi MZ } 2359f56e67bSKatayama Hirofumi MZ 2367aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 237c2c66affSColin Finck } 238c2c66affSColin Finck 239c2c66affSColin Finck void SelectionModel::FlipHorizontally() 240c2c66affSColin Finck { 241aac89519SKatayama Hirofumi MZ TakeOff(); 242aac89519SKatayama Hirofumi MZ 243aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 244aac89519SKatayama Hirofumi MZ if (m_hbmMask) 245aac89519SKatayama Hirofumi MZ { 246aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmMask); 247aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(), 248aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 249aac89519SKatayama Hirofumi MZ } 250aac89519SKatayama Hirofumi MZ if (m_hbmColor) 251aac89519SKatayama Hirofumi MZ { 252aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmColor); 253aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(), 254aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 255aac89519SKatayama Hirofumi MZ } 256aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 257aac89519SKatayama Hirofumi MZ 2587aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 259c2c66affSColin Finck } 260c2c66affSColin Finck 261c2c66affSColin Finck void SelectionModel::FlipVertically() 262c2c66affSColin Finck { 263aac89519SKatayama Hirofumi MZ TakeOff(); 264aac89519SKatayama Hirofumi MZ 265aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 266aac89519SKatayama Hirofumi MZ if (m_hbmMask) 267aac89519SKatayama Hirofumi MZ { 268aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmMask); 269aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(), 270aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 271aac89519SKatayama Hirofumi MZ } 272aac89519SKatayama Hirofumi MZ if (m_hbmColor) 273aac89519SKatayama Hirofumi MZ { 274aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmColor); 275aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(), 276aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 277aac89519SKatayama Hirofumi MZ } 278aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 279aac89519SKatayama Hirofumi MZ 2807aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 281c2c66affSColin Finck } 282c2c66affSColin Finck 283c2c66affSColin Finck void SelectionModel::RotateNTimes90Degrees(int iN) 284c2c66affSColin Finck { 2852d909190SKatayama Hirofumi MZ HBITMAP hbm; 286aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld; 287aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 288aac89519SKatayama Hirofumi MZ 2892d909190SKatayama Hirofumi MZ switch (iN) 290c2c66affSColin Finck { 2917aadc1e1SKatayama Hirofumi MZ case 1: /* rotate 90 degrees */ 2927aadc1e1SKatayama Hirofumi MZ case 3: /* rotate 270 degrees */ 293aac89519SKatayama Hirofumi MZ TakeOff(); 2947aadc1e1SKatayama Hirofumi MZ 295aac89519SKatayama Hirofumi MZ if (m_hbmColor) 296aac89519SKatayama Hirofumi MZ { 297aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmColor); 298aac89519SKatayama Hirofumi MZ hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, FALSE); 299aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 300aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor); 301aac89519SKatayama Hirofumi MZ m_hbmColor = hbm; 302aac89519SKatayama Hirofumi MZ } 303aac89519SKatayama Hirofumi MZ if (m_hbmMask) 304aac89519SKatayama Hirofumi MZ { 305aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmMask); 306aac89519SKatayama Hirofumi MZ hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, TRUE); 307aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 308aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask); 309aac89519SKatayama Hirofumi MZ m_hbmMask = hbm; 310aac89519SKatayama Hirofumi MZ } 3117aadc1e1SKatayama Hirofumi MZ 3127aadc1e1SKatayama Hirofumi MZ SwapWidthAndHeight(); 3132d909190SKatayama Hirofumi MZ break; 314aac89519SKatayama Hirofumi MZ 3157aadc1e1SKatayama Hirofumi MZ case 2: /* rotate 180 degrees */ 316aac89519SKatayama Hirofumi MZ TakeOff(); 3177aadc1e1SKatayama Hirofumi MZ 318aac89519SKatayama Hirofumi MZ if (m_hbmColor) 319aac89519SKatayama Hirofumi MZ { 320aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmColor); 321aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(), 322aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 323aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 324aac89519SKatayama Hirofumi MZ } 325aac89519SKatayama Hirofumi MZ if (m_hbmMask) 326aac89519SKatayama Hirofumi MZ { 327aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmMask); 328aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(), 329aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 330aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 331aac89519SKatayama Hirofumi MZ } 3322d909190SKatayama Hirofumi MZ break; 333c2c66affSColin Finck } 334aac89519SKatayama Hirofumi MZ 335aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 3367aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 337c2c66affSColin Finck } 338c2c66affSColin Finck 339b5335fb9SKatayama Hirofumi MZ static void AttachHBITMAP(HBITMAP *phbm, HBITMAP hbmNew) 340b5335fb9SKatayama Hirofumi MZ { 341b5335fb9SKatayama Hirofumi MZ if (hbmNew == NULL) 342b5335fb9SKatayama Hirofumi MZ return; 343b5335fb9SKatayama Hirofumi MZ ::DeleteObject(*phbm); 344b5335fb9SKatayama Hirofumi MZ *phbm = hbmNew; 345b5335fb9SKatayama Hirofumi MZ } 346b5335fb9SKatayama Hirofumi MZ 347dfd06ee8SKatayama Hirofumi MZ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY) 348dfd06ee8SKatayama Hirofumi MZ { 349dfd06ee8SKatayama Hirofumi MZ if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0) 350dfd06ee8SKatayama Hirofumi MZ return; 351dfd06ee8SKatayama Hirofumi MZ 352aac89519SKatayama Hirofumi MZ TakeOff(); 353dfd06ee8SKatayama Hirofumi MZ 354b5335fb9SKatayama Hirofumi MZ INT oldWidth = m_rc.Width(), oldHeight = m_rc.Height(); 355dfd06ee8SKatayama Hirofumi MZ INT newWidth = oldWidth * nStretchPercentX / 100; 356dfd06ee8SKatayama Hirofumi MZ INT newHeight = oldHeight * nStretchPercentY / 100; 357dfd06ee8SKatayama Hirofumi MZ 358b5335fb9SKatayama Hirofumi MZ HBITMAP hbmColor = m_hbmColor, hbmMask = m_hbmMask; 3599afcbea2SKatayama Hirofumi MZ 360b5335fb9SKatayama Hirofumi MZ if (hbmMask == NULL) 361b5335fb9SKatayama Hirofumi MZ hbmMask = CreateMonoBitmap(oldWidth, oldHeight, TRUE); 3629afcbea2SKatayama Hirofumi MZ 363dfd06ee8SKatayama Hirofumi MZ if (oldWidth != newWidth || oldHeight != newHeight) 364dfd06ee8SKatayama Hirofumi MZ { 365b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, CopyDIBImage(hbmColor, newWidth, newHeight)); 366b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, CopyMonoImage(hbmMask, newWidth, newHeight)); 367dfd06ee8SKatayama Hirofumi MZ } 368dfd06ee8SKatayama Hirofumi MZ 369b5335fb9SKatayama Hirofumi MZ HGDIOBJ hbmOld; 370aac89519SKatayama Hirofumi MZ HDC hDC = ::CreateCompatibleDC(NULL); 371aac89519SKatayama Hirofumi MZ 372dfd06ee8SKatayama Hirofumi MZ if (nSkewDegX) 373dfd06ee8SKatayama Hirofumi MZ { 374b5335fb9SKatayama Hirofumi MZ hbmOld = ::SelectObject(hDC, hbmColor); 375b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegX, FALSE)); 376b5335fb9SKatayama Hirofumi MZ ::SelectObject(hDC, hbmMask); 377b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegX, FALSE, TRUE)); 3789afcbea2SKatayama Hirofumi MZ ::SelectObject(hDC, hbmOld); 379dfd06ee8SKatayama Hirofumi MZ } 380dfd06ee8SKatayama Hirofumi MZ 381dfd06ee8SKatayama Hirofumi MZ if (nSkewDegY) 382dfd06ee8SKatayama Hirofumi MZ { 383b5335fb9SKatayama Hirofumi MZ hbmOld = ::SelectObject(hDC, hbmColor); 384b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegY, TRUE)); 385b5335fb9SKatayama Hirofumi MZ ::SelectObject(hDC, hbmMask); 386b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegY, TRUE, TRUE)); 3879afcbea2SKatayama Hirofumi MZ ::SelectObject(hDC, hbmOld); 388dfd06ee8SKatayama Hirofumi MZ } 389dfd06ee8SKatayama Hirofumi MZ 390aac89519SKatayama Hirofumi MZ ::DeleteDC(hDC); 391aac89519SKatayama Hirofumi MZ 392b5335fb9SKatayama Hirofumi MZ InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask); 393b5335fb9SKatayama Hirofumi MZ 394aac89519SKatayama Hirofumi MZ m_bShow = TRUE; 3957aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 396dfd06ee8SKatayama Hirofumi MZ } 397dfd06ee8SKatayama Hirofumi MZ 398e8c7e300SKatayama Hirofumi MZ HBITMAP SelectionModel::CopyBitmap() 399c2c66affSColin Finck { 40096c7fe4cSKatayama Hirofumi MZ if (m_hbmColor == NULL) 40196c7fe4cSKatayama Hirofumi MZ GetSelectionContents(imageModel.GetDC()); 402e8c7e300SKatayama Hirofumi MZ return CopyDIBImage(m_hbmColor); 403c2c66affSColin Finck } 404c2c66affSColin Finck 405b5536e44SKatayama Hirofumi MZ int SelectionModel::PtStackSize() const 406c2c66affSColin Finck { 407c2c66affSColin Finck return m_iPtSP; 408c2c66affSColin Finck } 409c2c66affSColin Finck 410c2c66affSColin Finck void SelectionModel::DrawFramePoly(HDC hDCImage) 411c2c66affSColin Finck { 412aac89519SKatayama Hirofumi MZ /* draw the freehand selection inverted/xored */ 413aac89519SKatayama Hirofumi MZ Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE); 414c2c66affSColin Finck } 415c2c66affSColin Finck 416aac89519SKatayama Hirofumi MZ void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo) 417c2c66affSColin Finck { 418aac89519SKatayama Hirofumi MZ m_rc.left = min(ptFrom.x, ptTo.x); 419aac89519SKatayama Hirofumi MZ m_rc.top = min(ptFrom.y, ptTo.y); 420aac89519SKatayama Hirofumi MZ m_rc.right = max(ptFrom.x, ptTo.x); 421aac89519SKatayama Hirofumi MZ m_rc.bottom = max(ptFrom.y, ptTo.y); 422c2c66affSColin Finck } 423c2c66affSColin Finck 424cb98e91bSKatayama Hirofumi MZ void SelectionModel::Dragging(HITTEST hit, POINT pt) 425c2c66affSColin Finck { 426aac89519SKatayama Hirofumi MZ switch (hit) 427c2c66affSColin Finck { 428aac89519SKatayama Hirofumi MZ case HIT_NONE: 429c2c66affSColin Finck break; 430aac89519SKatayama Hirofumi MZ case HIT_UPPER_LEFT: 431aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x; 432aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y; 433c2c66affSColin Finck break; 434aac89519SKatayama Hirofumi MZ case HIT_UPPER_CENTER: 435aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y; 436c2c66affSColin Finck break; 437aac89519SKatayama Hirofumi MZ case HIT_UPPER_RIGHT: 438aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x; 439aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y; 440c2c66affSColin Finck break; 441aac89519SKatayama Hirofumi MZ case HIT_MIDDLE_LEFT: 442aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x; 443c2c66affSColin Finck break; 444aac89519SKatayama Hirofumi MZ case HIT_MIDDLE_RIGHT: 445aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x; 446c2c66affSColin Finck break; 447aac89519SKatayama Hirofumi MZ case HIT_LOWER_LEFT: 448aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x; 449aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y; 450c2c66affSColin Finck break; 451aac89519SKatayama Hirofumi MZ case HIT_LOWER_CENTER: 452aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y; 453c2c66affSColin Finck break; 454aac89519SKatayama Hirofumi MZ case HIT_LOWER_RIGHT: 455aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x; 456aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y; 457aac89519SKatayama Hirofumi MZ break; 458aac89519SKatayama Hirofumi MZ case HIT_BORDER: 459aac89519SKatayama Hirofumi MZ case HIT_INNER: 460aac89519SKatayama Hirofumi MZ OffsetRect(&m_rc, pt.x - m_ptHit.x, pt.y - m_ptHit.y); 461c2c66affSColin Finck break; 462c2c66affSColin Finck } 463aac89519SKatayama Hirofumi MZ m_ptHit = pt; 464c2c66affSColin Finck } 465c2c66affSColin Finck 466*ed9973f8SKatayama Hirofumi MZ void SelectionModel::ClearMaskImage() 467361a2ce4SKatayama Hirofumi MZ { 468aac89519SKatayama Hirofumi MZ if (m_hbmMask) 469aac89519SKatayama Hirofumi MZ { 470aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask); 471aac89519SKatayama Hirofumi MZ m_hbmMask = NULL; 472aac89519SKatayama Hirofumi MZ } 473aac89519SKatayama Hirofumi MZ } 474aac89519SKatayama Hirofumi MZ 475*ed9973f8SKatayama Hirofumi MZ void SelectionModel::ClearColorImage() 476aac89519SKatayama Hirofumi MZ { 477aac89519SKatayama Hirofumi MZ if (m_hbmColor) 478aac89519SKatayama Hirofumi MZ { 479aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor); 480aac89519SKatayama Hirofumi MZ m_hbmColor = NULL; 481aac89519SKatayama Hirofumi MZ } 482aac89519SKatayama Hirofumi MZ } 483aac89519SKatayama Hirofumi MZ 484e8c7e300SKatayama Hirofumi MZ void SelectionModel::HideSelection() 485e8c7e300SKatayama Hirofumi MZ { 4867aadc1e1SKatayama Hirofumi MZ m_bShow = m_bContentChanged = FALSE; 487*ed9973f8SKatayama Hirofumi MZ ClearColorImage(); 488*ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 489e8c7e300SKatayama Hirofumi MZ ::SetRectEmpty(&m_rc); 490e8c7e300SKatayama Hirofumi MZ ::SetRectEmpty(&m_rcOld); 491e8c7e300SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 492e8c7e300SKatayama Hirofumi MZ } 493e8c7e300SKatayama Hirofumi MZ 494e8c7e300SKatayama Hirofumi MZ void SelectionModel::DeleteSelection() 495aac89519SKatayama Hirofumi MZ { 496aac89519SKatayama Hirofumi MZ if (!m_bShow) 497aac89519SKatayama Hirofumi MZ return; 498aac89519SKatayama Hirofumi MZ 499e8c7e300SKatayama Hirofumi MZ TakeOff(); 500e8c7e300SKatayama Hirofumi MZ imageModel.PushImageForUndo(); 5017aadc1e1SKatayama Hirofumi MZ DrawBackground(imageModel.GetDC()); 502e8c7e300SKatayama Hirofumi MZ 503e8c7e300SKatayama Hirofumi MZ HideSelection(); 504361a2ce4SKatayama Hirofumi MZ } 5057aadc1e1SKatayama Hirofumi MZ 5067aadc1e1SKatayama Hirofumi MZ void SelectionModel::InvertSelection() 5077aadc1e1SKatayama Hirofumi MZ { 5087aadc1e1SKatayama Hirofumi MZ TakeOff(); 5097aadc1e1SKatayama Hirofumi MZ 5107aadc1e1SKatayama Hirofumi MZ BITMAP bm; 5117aadc1e1SKatayama Hirofumi MZ ::GetObject(m_hbmColor, sizeof(bm), &bm); 5127aadc1e1SKatayama Hirofumi MZ 5137aadc1e1SKatayama Hirofumi MZ HDC hdc = ::CreateCompatibleDC(NULL); 5147aadc1e1SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hdc, m_hbmColor); 5157aadc1e1SKatayama Hirofumi MZ RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight }; 5167aadc1e1SKatayama Hirofumi MZ ::InvertRect(hdc, &rc); 5177aadc1e1SKatayama Hirofumi MZ ::SelectObject(hdc, hbmOld); 5187aadc1e1SKatayama Hirofumi MZ ::DeleteDC(hdc); 5197aadc1e1SKatayama Hirofumi MZ 5207aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 5217aadc1e1SKatayama Hirofumi MZ } 5227aadc1e1SKatayama Hirofumi MZ 5237aadc1e1SKatayama Hirofumi MZ void SelectionModel::NotifyContentChanged() 5247aadc1e1SKatayama Hirofumi MZ { 5257aadc1e1SKatayama Hirofumi MZ m_bContentChanged = TRUE; 5267aadc1e1SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 5277aadc1e1SKatayama Hirofumi MZ } 5287aadc1e1SKatayama Hirofumi MZ 5297aadc1e1SKatayama Hirofumi MZ void SelectionModel::SwapWidthAndHeight() 5307aadc1e1SKatayama Hirofumi MZ { 5317aadc1e1SKatayama Hirofumi MZ INT cx = m_rc.Width(); 5327aadc1e1SKatayama Hirofumi MZ INT cy = m_rc.Height(); 5337aadc1e1SKatayama Hirofumi MZ m_rc.right = m_rc.left + cy; 5347aadc1e1SKatayama Hirofumi MZ m_rc.bottom = m_rc.top + cx; 5357aadc1e1SKatayama Hirofumi MZ } 536bbb33a6eSKatayama Hirofumi MZ 537bbb33a6eSKatayama Hirofumi MZ HBITMAP SelectionModel::LockBitmap() 538bbb33a6eSKatayama Hirofumi MZ { 539bbb33a6eSKatayama Hirofumi MZ HBITMAP hbm = m_hbmColor; 540bbb33a6eSKatayama Hirofumi MZ m_hbmColor = NULL; 541bbb33a6eSKatayama Hirofumi MZ return hbm; 542bbb33a6eSKatayama Hirofumi MZ } 543bbb33a6eSKatayama Hirofumi MZ 544bbb33a6eSKatayama Hirofumi MZ void SelectionModel::UnlockBitmap(HBITMAP hbmLocked) 545bbb33a6eSKatayama Hirofumi MZ { 546bbb33a6eSKatayama Hirofumi MZ m_hbmColor = hbmLocked; 547bbb33a6eSKatayama Hirofumi MZ } 548*ed9973f8SKatayama Hirofumi MZ 549*ed9973f8SKatayama Hirofumi MZ void SelectionModel::StretchSelection(BOOL bShrink) 550*ed9973f8SKatayama Hirofumi MZ { 551*ed9973f8SKatayama Hirofumi MZ if (!m_bShow) 552*ed9973f8SKatayama Hirofumi MZ return; 553*ed9973f8SKatayama Hirofumi MZ 554*ed9973f8SKatayama Hirofumi MZ TakeOff(); 555*ed9973f8SKatayama Hirofumi MZ 556*ed9973f8SKatayama Hirofumi MZ INT cx = m_rc.Width(), cy = m_rc.Height(); 557*ed9973f8SKatayama Hirofumi MZ 558*ed9973f8SKatayama Hirofumi MZ if (bShrink) 559*ed9973f8SKatayama Hirofumi MZ m_rc.InflateRect(-cx / 4, -cy / 4); 560*ed9973f8SKatayama Hirofumi MZ else 561*ed9973f8SKatayama Hirofumi MZ m_rc.InflateRect(+cx / 2, +cy / 2); 562*ed9973f8SKatayama Hirofumi MZ 563*ed9973f8SKatayama Hirofumi MZ // The selection area must exist there 564*ed9973f8SKatayama Hirofumi MZ if (m_rc.Width() <= 0) 565*ed9973f8SKatayama Hirofumi MZ m_rc.right = m_rc.left + 1; 566*ed9973f8SKatayama Hirofumi MZ if (m_rc.Height() <= 0) 567*ed9973f8SKatayama Hirofumi MZ m_rc.bottom = m_rc.top + 1; 568*ed9973f8SKatayama Hirofumi MZ 569*ed9973f8SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 570*ed9973f8SKatayama Hirofumi MZ } 571