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); 26*e5792200SKatayama Hirofumi MZ m_ptHit = { -1, -1 }; 273fa95ab9SKatayama Hirofumi MZ } 28c2c66affSColin Finck 293fa95ab9SKatayama Hirofumi MZ SelectionModel::~SelectionModel() 303fa95ab9SKatayama Hirofumi MZ { 31ed9973f8SKatayama Hirofumi MZ ClearColorImage(); 32ed9973f8SKatayama 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 { 74*e5792200SKatayama Hirofumi MZ CRect rc; 75*e5792200SKatayama Hirofumi MZ getBoundaryOfPtStack(rc, m_iPtSP, m_ptStack); 76aac89519SKatayama Hirofumi MZ 77e8c7e300SKatayama Hirofumi MZ m_rc = m_rcOld = rc; 78aac89519SKatayama Hirofumi MZ 79ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 80aac89519SKatayama Hirofumi MZ 81e8c7e300SKatayama Hirofumi MZ ShiftPtStack(-m_rcOld.left, -m_rcOld.top); 82e8c7e300SKatayama Hirofumi MZ 83aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 84aac89519SKatayama Hirofumi MZ m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL); 85aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask); 86e8c7e300SKatayama Hirofumi MZ ::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH)); 87aac89519SKatayama Hirofumi MZ HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN)); 88aac89519SKatayama Hirofumi MZ HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH)); 89aac89519SKatayama Hirofumi MZ ::Polygon(hdcMem, m_ptStack, m_iPtSP); 90aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbrOld); 91aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hPenOld); 92aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 93aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 94e8c7e300SKatayama Hirofumi MZ 95e8c7e300SKatayama Hirofumi MZ ShiftPtStack(+m_rcOld.left, +m_rcOld.top); 96c2c66affSColin Finck } 97c2c66affSColin Finck 98c2c66affSColin Finck void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg) 99c2c66affSColin Finck { 100e8c7e300SKatayama Hirofumi MZ if (::IsRectEmpty(&m_rcOld)) 101e8c7e300SKatayama Hirofumi MZ return; 102aac89519SKatayama Hirofumi MZ 103aac89519SKatayama Hirofumi MZ HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN)); 104aac89519SKatayama Hirofumi MZ HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg)); 105aac89519SKatayama Hirofumi MZ ::Polygon(hDCImage, m_ptStack, m_iPtSP); 106aac89519SKatayama Hirofumi MZ ::DeleteObject(::SelectObject(hDCImage, hbrOld)); 107aac89519SKatayama Hirofumi MZ ::SelectObject(hDCImage, hPenOld); 108c2c66affSColin Finck } 109c2c66affSColin Finck 110c2c66affSColin Finck void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg) 111c2c66affSColin Finck { 112e8c7e300SKatayama Hirofumi MZ if (::IsRectEmpty(&m_rcOld)) 113e8c7e300SKatayama Hirofumi MZ return; 114e8c7e300SKatayama Hirofumi MZ 115e8c7e300SKatayama Hirofumi MZ Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1); 116c2c66affSColin Finck } 117c2c66affSColin Finck 1187aadc1e1SKatayama Hirofumi MZ void SelectionModel::DrawBackground(HDC hDCImage) 1197aadc1e1SKatayama Hirofumi MZ { 1207aadc1e1SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_FREESEL) 1217aadc1e1SKatayama Hirofumi MZ DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor()); 1227aadc1e1SKatayama Hirofumi MZ else 1237aadc1e1SKatayama Hirofumi MZ DrawBackgroundRect(hDCImage, paletteModel.GetBgColor()); 1247aadc1e1SKatayama Hirofumi MZ } 1257aadc1e1SKatayama Hirofumi MZ 126e8c7e300SKatayama Hirofumi MZ void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent) 127c2c66affSColin Finck { 128e8c7e300SKatayama Hirofumi MZ CRect rc = m_rc; 129aac89519SKatayama Hirofumi MZ if (::IsRectEmpty(&rc)) 130aac89519SKatayama Hirofumi MZ return; 131aac89519SKatayama Hirofumi MZ 132aac89519SKatayama Hirofumi MZ BITMAP bm; 133640d67d1SKatayama Hirofumi MZ if (!GetObjectW(m_hbmColor, sizeof(BITMAP), &bm)) 134e8c7e300SKatayama Hirofumi MZ return; 135aac89519SKatayama Hirofumi MZ 136aac89519SKatayama Hirofumi MZ COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID); 137aac89519SKatayama Hirofumi MZ 138aac89519SKatayama Hirofumi MZ HDC hMemDC = CreateCompatibleDC(hDCImage); 139aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld = SelectObject(hMemDC, m_hbmColor); 140aac89519SKatayama Hirofumi MZ ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(), 141aac89519SKatayama Hirofumi MZ hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor); 142aac89519SKatayama Hirofumi MZ SelectObject(hMemDC, hbmOld); 143aac89519SKatayama Hirofumi MZ DeleteDC(hMemDC); 144aac89519SKatayama Hirofumi MZ } 145aac89519SKatayama Hirofumi MZ 146d7ece626SKatayama Hirofumi MZ HBITMAP SelectionModel::GetSelectionContents() 147aac89519SKatayama Hirofumi MZ { 148d7ece626SKatayama Hirofumi MZ if (m_hbmColor) 149d7ece626SKatayama Hirofumi MZ return CopyDIBImage(m_hbmColor, m_rc.Width(), m_rc.Height()); 150aac89519SKatayama Hirofumi MZ 151764e5505SKatayama Hirofumi MZ HBITMAP hbmWhole = imageModel.LockBitmap(); 152764e5505SKatayama Hirofumi MZ HBITMAP hbmPart = getSubImage(hbmWhole, m_rc); 153764e5505SKatayama Hirofumi MZ imageModel.UnlockBitmap(hbmWhole); 154764e5505SKatayama Hirofumi MZ return hbmPart; 155aac89519SKatayama Hirofumi MZ } 156aac89519SKatayama Hirofumi MZ 157e8c7e300SKatayama Hirofumi MZ BOOL SelectionModel::IsLanded() const 158e8c7e300SKatayama Hirofumi MZ { 159e8c7e300SKatayama Hirofumi MZ return !m_hbmColor; 160e8c7e300SKatayama Hirofumi MZ } 161e8c7e300SKatayama Hirofumi MZ 162aac89519SKatayama Hirofumi MZ BOOL SelectionModel::TakeOff() 163aac89519SKatayama Hirofumi MZ { 164e8c7e300SKatayama Hirofumi MZ if (!IsLanded() || ::IsRectEmpty(&m_rc)) 165aac89519SKatayama Hirofumi MZ return FALSE; 166aac89519SKatayama Hirofumi MZ 167ed9973f8SKatayama Hirofumi MZ // The background color is needed for transparency of selection 168e8c7e300SKatayama Hirofumi MZ m_rgbBack = paletteModel.GetBgColor(); 169ed9973f8SKatayama Hirofumi MZ 170ed9973f8SKatayama Hirofumi MZ // Get the contents of the selection area 171d7ece626SKatayama Hirofumi MZ ClearColorImage(); 172d7ece626SKatayama Hirofumi MZ m_hbmColor = GetSelectionContents(); 173aac89519SKatayama Hirofumi MZ 174ed9973f8SKatayama Hirofumi MZ // RectSel doesn't need the mask image 175e8c7e300SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_RECTSEL) 176ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 177e8c7e300SKatayama Hirofumi MZ 178ed9973f8SKatayama Hirofumi MZ // Save the selection area 179e8c7e300SKatayama Hirofumi MZ m_rcOld = m_rc; 180c2c66affSColin Finck 181cbc63d87SKatayama Hirofumi MZ if (toolsModel.GetActiveTool() == TOOL_RECTSEL) 182cbc63d87SKatayama Hirofumi MZ { 183cbc63d87SKatayama Hirofumi MZ imageModel.PushImageForUndo(); 184cbc63d87SKatayama Hirofumi MZ selectionModel.DrawBackgroundRect(imageModel.GetDC(), selectionModel.m_rgbBack); 185cbc63d87SKatayama Hirofumi MZ } 186cbc63d87SKatayama Hirofumi MZ else if (toolsModel.GetActiveTool() == TOOL_FREESEL) 187cbc63d87SKatayama Hirofumi MZ { 188cbc63d87SKatayama Hirofumi MZ imageModel.PushImageForUndo(); 189cbc63d87SKatayama Hirofumi MZ selectionModel.DrawBackgroundPoly(imageModel.GetDC(), selectionModel.m_rgbBack); 190cbc63d87SKatayama Hirofumi MZ } 191cbc63d87SKatayama Hirofumi MZ 192bfd42c67SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 193aac89519SKatayama Hirofumi MZ return TRUE; 194c2c66affSColin Finck } 195c2c66affSColin Finck 196aac89519SKatayama Hirofumi MZ void SelectionModel::Landing() 197c2c66affSColin Finck { 198e8c7e300SKatayama Hirofumi MZ if (IsLanded() && !m_bShow) 199e8c7e300SKatayama Hirofumi MZ { 200e8c7e300SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 201aac89519SKatayama Hirofumi MZ return; 202e8c7e300SKatayama Hirofumi MZ } 203aac89519SKatayama Hirofumi MZ 204e8c7e300SKatayama Hirofumi MZ m_bShow = FALSE; 205aac89519SKatayama Hirofumi MZ 2067aadc1e1SKatayama Hirofumi MZ if (m_bContentChanged || 2077aadc1e1SKatayama Hirofumi MZ (!::EqualRect(m_rc, m_rcOld) && !::IsRectEmpty(m_rc) && !::IsRectEmpty(m_rcOld))) 208e8c7e300SKatayama Hirofumi MZ { 2092b623c1dSKatayama Hirofumi MZ imageModel.PushImageForUndo(); 210e8c7e300SKatayama Hirofumi MZ 211e8c7e300SKatayama Hirofumi MZ canvasWindow.m_drawing = FALSE; 212e8c7e300SKatayama Hirofumi MZ toolsModel.OnDrawOverlayOnImage(imageModel.GetDC()); 213e8c7e300SKatayama Hirofumi MZ } 214e8c7e300SKatayama Hirofumi MZ 215e8c7e300SKatayama Hirofumi MZ HideSelection(); 216c2c66affSColin Finck } 217c2c66affSColin Finck 2189afcbea2SKatayama Hirofumi MZ void SelectionModel::InsertFromHBITMAP(HBITMAP hbmColor, INT x, INT y, HBITMAP hbmMask) 219c2c66affSColin Finck { 220aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor); 221b5335fb9SKatayama Hirofumi MZ m_hbmColor = hbmColor; 222c2c66affSColin Finck 223aac89519SKatayama Hirofumi MZ m_rc.left = x; 224aac89519SKatayama Hirofumi MZ m_rc.top = y; 2259afcbea2SKatayama Hirofumi MZ m_rc.right = x + GetDIBWidth(hbmColor); 2269afcbea2SKatayama Hirofumi MZ m_rc.bottom = y + GetDIBHeight(hbmColor); 2279afcbea2SKatayama Hirofumi MZ 2289afcbea2SKatayama Hirofumi MZ if (hbmMask) 2299afcbea2SKatayama Hirofumi MZ { 2309afcbea2SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask); 231b5335fb9SKatayama Hirofumi MZ m_hbmMask = hbmMask; 2329afcbea2SKatayama Hirofumi MZ } 2339afcbea2SKatayama Hirofumi MZ else 2349afcbea2SKatayama Hirofumi MZ { 235ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 2369afcbea2SKatayama Hirofumi MZ } 2379f56e67bSKatayama Hirofumi MZ 2387aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 239c2c66affSColin Finck } 240c2c66affSColin Finck 241c2c66affSColin Finck void SelectionModel::FlipHorizontally() 242c2c66affSColin Finck { 243aac89519SKatayama Hirofumi MZ TakeOff(); 244aac89519SKatayama Hirofumi MZ 245aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 246aac89519SKatayama Hirofumi MZ if (m_hbmMask) 247aac89519SKatayama Hirofumi MZ { 248aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmMask); 249aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(), 250aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 251aac89519SKatayama Hirofumi MZ } 252aac89519SKatayama Hirofumi MZ if (m_hbmColor) 253aac89519SKatayama Hirofumi MZ { 254aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmColor); 255aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(), 256aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 257aac89519SKatayama Hirofumi MZ } 258aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 259aac89519SKatayama Hirofumi MZ 2607aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 261c2c66affSColin Finck } 262c2c66affSColin Finck 263c2c66affSColin Finck void SelectionModel::FlipVertically() 264c2c66affSColin Finck { 265aac89519SKatayama Hirofumi MZ TakeOff(); 266aac89519SKatayama Hirofumi MZ 267aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 268aac89519SKatayama Hirofumi MZ if (m_hbmMask) 269aac89519SKatayama Hirofumi MZ { 270aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmMask); 271aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(), 272aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 273aac89519SKatayama Hirofumi MZ } 274aac89519SKatayama Hirofumi MZ if (m_hbmColor) 275aac89519SKatayama Hirofumi MZ { 276aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, m_hbmColor); 277aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(), 278aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 279aac89519SKatayama Hirofumi MZ } 280aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 281aac89519SKatayama Hirofumi MZ 2827aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 283c2c66affSColin Finck } 284c2c66affSColin Finck 285c2c66affSColin Finck void SelectionModel::RotateNTimes90Degrees(int iN) 286c2c66affSColin Finck { 2872d909190SKatayama Hirofumi MZ HBITMAP hbm; 288aac89519SKatayama Hirofumi MZ HGDIOBJ hbmOld; 289aac89519SKatayama Hirofumi MZ HDC hdcMem = ::CreateCompatibleDC(NULL); 290aac89519SKatayama Hirofumi MZ 2912d909190SKatayama Hirofumi MZ switch (iN) 292c2c66affSColin Finck { 2937aadc1e1SKatayama Hirofumi MZ case 1: /* rotate 90 degrees */ 2947aadc1e1SKatayama Hirofumi MZ case 3: /* rotate 270 degrees */ 295aac89519SKatayama Hirofumi MZ TakeOff(); 2967aadc1e1SKatayama Hirofumi MZ 297aac89519SKatayama Hirofumi MZ if (m_hbmColor) 298aac89519SKatayama Hirofumi MZ { 299aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmColor); 300aac89519SKatayama Hirofumi MZ hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, FALSE); 301aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 302aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor); 303aac89519SKatayama Hirofumi MZ m_hbmColor = hbm; 304aac89519SKatayama Hirofumi MZ } 305aac89519SKatayama Hirofumi MZ if (m_hbmMask) 306aac89519SKatayama Hirofumi MZ { 307aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmMask); 308aac89519SKatayama Hirofumi MZ hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, TRUE); 309aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 310aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask); 311aac89519SKatayama Hirofumi MZ m_hbmMask = hbm; 312aac89519SKatayama Hirofumi MZ } 3137aadc1e1SKatayama Hirofumi MZ 3147aadc1e1SKatayama Hirofumi MZ SwapWidthAndHeight(); 3152d909190SKatayama Hirofumi MZ break; 316aac89519SKatayama Hirofumi MZ 3177aadc1e1SKatayama Hirofumi MZ case 2: /* rotate 180 degrees */ 318aac89519SKatayama Hirofumi MZ TakeOff(); 3197aadc1e1SKatayama Hirofumi MZ 320aac89519SKatayama Hirofumi MZ if (m_hbmColor) 321aac89519SKatayama Hirofumi MZ { 322aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmColor); 323aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(), 324aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 325aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 326aac89519SKatayama Hirofumi MZ } 327aac89519SKatayama Hirofumi MZ if (m_hbmMask) 328aac89519SKatayama Hirofumi MZ { 329aac89519SKatayama Hirofumi MZ hbmOld = ::SelectObject(hdcMem, m_hbmMask); 330aac89519SKatayama Hirofumi MZ ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(), 331aac89519SKatayama Hirofumi MZ hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY); 332aac89519SKatayama Hirofumi MZ ::SelectObject(hdcMem, hbmOld); 333aac89519SKatayama Hirofumi MZ } 3342d909190SKatayama Hirofumi MZ break; 335c2c66affSColin Finck } 336aac89519SKatayama Hirofumi MZ 337aac89519SKatayama Hirofumi MZ ::DeleteDC(hdcMem); 3387aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 339c2c66affSColin Finck } 340c2c66affSColin Finck 341b5335fb9SKatayama Hirofumi MZ static void AttachHBITMAP(HBITMAP *phbm, HBITMAP hbmNew) 342b5335fb9SKatayama Hirofumi MZ { 343b5335fb9SKatayama Hirofumi MZ if (hbmNew == NULL) 344b5335fb9SKatayama Hirofumi MZ return; 345b5335fb9SKatayama Hirofumi MZ ::DeleteObject(*phbm); 346b5335fb9SKatayama Hirofumi MZ *phbm = hbmNew; 347b5335fb9SKatayama Hirofumi MZ } 348b5335fb9SKatayama Hirofumi MZ 349dfd06ee8SKatayama Hirofumi MZ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY) 350dfd06ee8SKatayama Hirofumi MZ { 351dfd06ee8SKatayama Hirofumi MZ if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0) 352dfd06ee8SKatayama Hirofumi MZ return; 353dfd06ee8SKatayama Hirofumi MZ 354aac89519SKatayama Hirofumi MZ TakeOff(); 355dfd06ee8SKatayama Hirofumi MZ 356b5335fb9SKatayama Hirofumi MZ INT oldWidth = m_rc.Width(), oldHeight = m_rc.Height(); 357dfd06ee8SKatayama Hirofumi MZ INT newWidth = oldWidth * nStretchPercentX / 100; 358dfd06ee8SKatayama Hirofumi MZ INT newHeight = oldHeight * nStretchPercentY / 100; 359dfd06ee8SKatayama Hirofumi MZ 360b5335fb9SKatayama Hirofumi MZ HBITMAP hbmColor = m_hbmColor, hbmMask = m_hbmMask; 3619afcbea2SKatayama Hirofumi MZ 362b5335fb9SKatayama Hirofumi MZ if (hbmMask == NULL) 363b5335fb9SKatayama Hirofumi MZ hbmMask = CreateMonoBitmap(oldWidth, oldHeight, TRUE); 3649afcbea2SKatayama Hirofumi MZ 365dfd06ee8SKatayama Hirofumi MZ if (oldWidth != newWidth || oldHeight != newHeight) 366dfd06ee8SKatayama Hirofumi MZ { 367b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, CopyDIBImage(hbmColor, newWidth, newHeight)); 368b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, CopyMonoImage(hbmMask, newWidth, newHeight)); 369dfd06ee8SKatayama Hirofumi MZ } 370dfd06ee8SKatayama Hirofumi MZ 371b5335fb9SKatayama Hirofumi MZ HGDIOBJ hbmOld; 372aac89519SKatayama Hirofumi MZ HDC hDC = ::CreateCompatibleDC(NULL); 373aac89519SKatayama Hirofumi MZ 374dfd06ee8SKatayama Hirofumi MZ if (nSkewDegX) 375dfd06ee8SKatayama Hirofumi MZ { 376b5335fb9SKatayama Hirofumi MZ hbmOld = ::SelectObject(hDC, hbmColor); 377b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegX, FALSE)); 378b5335fb9SKatayama Hirofumi MZ ::SelectObject(hDC, hbmMask); 379b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegX, FALSE, TRUE)); 3809afcbea2SKatayama Hirofumi MZ ::SelectObject(hDC, hbmOld); 381dfd06ee8SKatayama Hirofumi MZ } 382dfd06ee8SKatayama Hirofumi MZ 383dfd06ee8SKatayama Hirofumi MZ if (nSkewDegY) 384dfd06ee8SKatayama Hirofumi MZ { 385b5335fb9SKatayama Hirofumi MZ hbmOld = ::SelectObject(hDC, hbmColor); 386b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegY, TRUE)); 387b5335fb9SKatayama Hirofumi MZ ::SelectObject(hDC, hbmMask); 388b5335fb9SKatayama Hirofumi MZ AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegY, TRUE, TRUE)); 3899afcbea2SKatayama Hirofumi MZ ::SelectObject(hDC, hbmOld); 390dfd06ee8SKatayama Hirofumi MZ } 391dfd06ee8SKatayama Hirofumi MZ 392aac89519SKatayama Hirofumi MZ ::DeleteDC(hDC); 393aac89519SKatayama Hirofumi MZ 394b5335fb9SKatayama Hirofumi MZ InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask); 395b5335fb9SKatayama Hirofumi MZ 396aac89519SKatayama Hirofumi MZ m_bShow = TRUE; 3977aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 398dfd06ee8SKatayama Hirofumi MZ } 399dfd06ee8SKatayama Hirofumi MZ 400b5536e44SKatayama Hirofumi MZ int SelectionModel::PtStackSize() const 401c2c66affSColin Finck { 402c2c66affSColin Finck return m_iPtSP; 403c2c66affSColin Finck } 404c2c66affSColin Finck 405c2c66affSColin Finck void SelectionModel::DrawFramePoly(HDC hDCImage) 406c2c66affSColin Finck { 407aac89519SKatayama Hirofumi MZ /* draw the freehand selection inverted/xored */ 408aac89519SKatayama Hirofumi MZ Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE); 409c2c66affSColin Finck } 410c2c66affSColin Finck 411aac89519SKatayama Hirofumi MZ void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo) 412c2c66affSColin Finck { 413aac89519SKatayama Hirofumi MZ m_rc.left = min(ptFrom.x, ptTo.x); 414aac89519SKatayama Hirofumi MZ m_rc.top = min(ptFrom.y, ptTo.y); 415aac89519SKatayama Hirofumi MZ m_rc.right = max(ptFrom.x, ptTo.x); 416aac89519SKatayama Hirofumi MZ m_rc.bottom = max(ptFrom.y, ptTo.y); 417c2c66affSColin Finck } 418c2c66affSColin Finck 419cb98e91bSKatayama Hirofumi MZ void SelectionModel::Dragging(HITTEST hit, POINT pt) 420c2c66affSColin Finck { 421aac89519SKatayama Hirofumi MZ switch (hit) 422c2c66affSColin Finck { 423aac89519SKatayama Hirofumi MZ case HIT_NONE: 424c2c66affSColin Finck break; 425aac89519SKatayama Hirofumi MZ case HIT_UPPER_LEFT: 426aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x; 427aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y; 428c2c66affSColin Finck break; 429aac89519SKatayama Hirofumi MZ case HIT_UPPER_CENTER: 430aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y; 431c2c66affSColin Finck break; 432aac89519SKatayama Hirofumi MZ case HIT_UPPER_RIGHT: 433aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x; 434aac89519SKatayama Hirofumi MZ m_rc.top += pt.y - m_ptHit.y; 435c2c66affSColin Finck break; 436aac89519SKatayama Hirofumi MZ case HIT_MIDDLE_LEFT: 437aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x; 438c2c66affSColin Finck break; 439aac89519SKatayama Hirofumi MZ case HIT_MIDDLE_RIGHT: 440aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x; 441c2c66affSColin Finck break; 442aac89519SKatayama Hirofumi MZ case HIT_LOWER_LEFT: 443aac89519SKatayama Hirofumi MZ m_rc.left += pt.x - m_ptHit.x; 444aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y; 445c2c66affSColin Finck break; 446aac89519SKatayama Hirofumi MZ case HIT_LOWER_CENTER: 447aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y; 448c2c66affSColin Finck break; 449aac89519SKatayama Hirofumi MZ case HIT_LOWER_RIGHT: 450aac89519SKatayama Hirofumi MZ m_rc.right += pt.x - m_ptHit.x; 451aac89519SKatayama Hirofumi MZ m_rc.bottom += pt.y - m_ptHit.y; 452aac89519SKatayama Hirofumi MZ break; 453aac89519SKatayama Hirofumi MZ case HIT_BORDER: 454aac89519SKatayama Hirofumi MZ case HIT_INNER: 455aac89519SKatayama Hirofumi MZ OffsetRect(&m_rc, pt.x - m_ptHit.x, pt.y - m_ptHit.y); 456c2c66affSColin Finck break; 457c2c66affSColin Finck } 458aac89519SKatayama Hirofumi MZ m_ptHit = pt; 459c2c66affSColin Finck } 460c2c66affSColin Finck 461ed9973f8SKatayama Hirofumi MZ void SelectionModel::ClearMaskImage() 462361a2ce4SKatayama Hirofumi MZ { 463aac89519SKatayama Hirofumi MZ if (m_hbmMask) 464aac89519SKatayama Hirofumi MZ { 465aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmMask); 466aac89519SKatayama Hirofumi MZ m_hbmMask = NULL; 467aac89519SKatayama Hirofumi MZ } 468aac89519SKatayama Hirofumi MZ } 469aac89519SKatayama Hirofumi MZ 470ed9973f8SKatayama Hirofumi MZ void SelectionModel::ClearColorImage() 471aac89519SKatayama Hirofumi MZ { 472aac89519SKatayama Hirofumi MZ if (m_hbmColor) 473aac89519SKatayama Hirofumi MZ { 474aac89519SKatayama Hirofumi MZ ::DeleteObject(m_hbmColor); 475aac89519SKatayama Hirofumi MZ m_hbmColor = NULL; 476aac89519SKatayama Hirofumi MZ } 477aac89519SKatayama Hirofumi MZ } 478aac89519SKatayama Hirofumi MZ 479e8c7e300SKatayama Hirofumi MZ void SelectionModel::HideSelection() 480e8c7e300SKatayama Hirofumi MZ { 4817aadc1e1SKatayama Hirofumi MZ m_bShow = m_bContentChanged = FALSE; 482ed9973f8SKatayama Hirofumi MZ ClearColorImage(); 483ed9973f8SKatayama Hirofumi MZ ClearMaskImage(); 484e8c7e300SKatayama Hirofumi MZ ::SetRectEmpty(&m_rc); 485e8c7e300SKatayama Hirofumi MZ ::SetRectEmpty(&m_rcOld); 486e8c7e300SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 487e8c7e300SKatayama Hirofumi MZ } 488e8c7e300SKatayama Hirofumi MZ 489e8c7e300SKatayama Hirofumi MZ void SelectionModel::DeleteSelection() 490aac89519SKatayama Hirofumi MZ { 491aac89519SKatayama Hirofumi MZ if (!m_bShow) 492aac89519SKatayama Hirofumi MZ return; 493aac89519SKatayama Hirofumi MZ 494e8c7e300SKatayama Hirofumi MZ TakeOff(); 495e8c7e300SKatayama Hirofumi MZ imageModel.PushImageForUndo(); 4967aadc1e1SKatayama Hirofumi MZ DrawBackground(imageModel.GetDC()); 497e8c7e300SKatayama Hirofumi MZ 498e8c7e300SKatayama Hirofumi MZ HideSelection(); 499361a2ce4SKatayama Hirofumi MZ } 5007aadc1e1SKatayama Hirofumi MZ 5017aadc1e1SKatayama Hirofumi MZ void SelectionModel::InvertSelection() 5027aadc1e1SKatayama Hirofumi MZ { 5037aadc1e1SKatayama Hirofumi MZ TakeOff(); 5047aadc1e1SKatayama Hirofumi MZ 5057aadc1e1SKatayama Hirofumi MZ BITMAP bm; 506640d67d1SKatayama Hirofumi MZ ::GetObjectW(m_hbmColor, sizeof(bm), &bm); 5077aadc1e1SKatayama Hirofumi MZ 5087aadc1e1SKatayama Hirofumi MZ HDC hdc = ::CreateCompatibleDC(NULL); 5097aadc1e1SKatayama Hirofumi MZ HGDIOBJ hbmOld = ::SelectObject(hdc, m_hbmColor); 5107aadc1e1SKatayama Hirofumi MZ RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight }; 5117aadc1e1SKatayama Hirofumi MZ ::InvertRect(hdc, &rc); 5127aadc1e1SKatayama Hirofumi MZ ::SelectObject(hdc, hbmOld); 5137aadc1e1SKatayama Hirofumi MZ ::DeleteDC(hdc); 5147aadc1e1SKatayama Hirofumi MZ 5157aadc1e1SKatayama Hirofumi MZ NotifyContentChanged(); 5167aadc1e1SKatayama Hirofumi MZ } 5177aadc1e1SKatayama Hirofumi MZ 5187aadc1e1SKatayama Hirofumi MZ void SelectionModel::NotifyContentChanged() 5197aadc1e1SKatayama Hirofumi MZ { 5207aadc1e1SKatayama Hirofumi MZ m_bContentChanged = TRUE; 5217aadc1e1SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 5227aadc1e1SKatayama Hirofumi MZ } 5237aadc1e1SKatayama Hirofumi MZ 5247aadc1e1SKatayama Hirofumi MZ void SelectionModel::SwapWidthAndHeight() 5257aadc1e1SKatayama Hirofumi MZ { 5267aadc1e1SKatayama Hirofumi MZ INT cx = m_rc.Width(); 5277aadc1e1SKatayama Hirofumi MZ INT cy = m_rc.Height(); 5287aadc1e1SKatayama Hirofumi MZ m_rc.right = m_rc.left + cy; 5297aadc1e1SKatayama Hirofumi MZ m_rc.bottom = m_rc.top + cx; 5307aadc1e1SKatayama Hirofumi MZ } 531bbb33a6eSKatayama Hirofumi MZ 532ed9973f8SKatayama Hirofumi MZ void SelectionModel::StretchSelection(BOOL bShrink) 533ed9973f8SKatayama Hirofumi MZ { 534ed9973f8SKatayama Hirofumi MZ if (!m_bShow) 535ed9973f8SKatayama Hirofumi MZ return; 536ed9973f8SKatayama Hirofumi MZ 537ed9973f8SKatayama Hirofumi MZ TakeOff(); 538ed9973f8SKatayama Hirofumi MZ 539ed9973f8SKatayama Hirofumi MZ INT cx = m_rc.Width(), cy = m_rc.Height(); 540ed9973f8SKatayama Hirofumi MZ 541ed9973f8SKatayama Hirofumi MZ if (bShrink) 542ed9973f8SKatayama Hirofumi MZ m_rc.InflateRect(-cx / 4, -cy / 4); 543ed9973f8SKatayama Hirofumi MZ else 544ed9973f8SKatayama Hirofumi MZ m_rc.InflateRect(+cx / 2, +cy / 2); 545ed9973f8SKatayama Hirofumi MZ 546ed9973f8SKatayama Hirofumi MZ // The selection area must exist there 547ed9973f8SKatayama Hirofumi MZ if (m_rc.Width() <= 0) 548ed9973f8SKatayama Hirofumi MZ m_rc.right = m_rc.left + 1; 549ed9973f8SKatayama Hirofumi MZ if (m_rc.Height() <= 0) 550ed9973f8SKatayama Hirofumi MZ m_rc.bottom = m_rc.top + 1; 551ed9973f8SKatayama Hirofumi MZ 552ed9973f8SKatayama Hirofumi MZ imageModel.NotifyImageChanged(); 553ed9973f8SKatayama Hirofumi MZ } 554