1 /* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL 4 * FILE: base/applications/mspaint/history.cpp 5 * PURPOSE: Undo and redo functionality 6 * PROGRAMMERS: Benedikt Freisen 7 */ 8 9 /* INCLUDES *********************************************************/ 10 11 #include "precomp.h" 12 13 /* FUNCTIONS ********************************************************/ 14 15 void ImageModel::NotifyDimensionsChanged() 16 { 17 imageArea.SendMessage(WM_IMAGEMODELDIMENSIONSCHANGED); 18 } 19 20 void ImageModel::NotifyImageChanged() 21 { 22 imageArea.SendMessage(WM_IMAGEMODELIMAGECHANGED); 23 } 24 25 ImageModel::ImageModel() 26 { 27 currInd = 0; 28 undoSteps = 0; 29 redoSteps = 0; 30 imageSaved = TRUE; 31 32 // prepare a minimal usable bitmap 33 int imgXRes = 1; 34 int imgYRes = 1; 35 36 hDrawingDC = CreateCompatibleDC(NULL); 37 SelectObject(hDrawingDC, CreatePen(PS_SOLID, 0, paletteModel.GetFgColor())); 38 SelectObject(hDrawingDC, CreateSolidBrush(paletteModel.GetBgColor())); 39 40 hBms[0] = CreateDIBWithProperties(imgXRes, imgYRes); 41 SelectObject(hDrawingDC, hBms[0]); 42 Rectangle(hDrawingDC, 0 - 1, 0 - 1, imgXRes + 1, imgYRes + 1); 43 } 44 45 void ImageModel::CopyPrevious() 46 { 47 DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]); 48 hBms[(currInd + 1) % HISTORYSIZE] = (HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG); 49 currInd = (currInd + 1) % HISTORYSIZE; 50 if (undoSteps < HISTORYSIZE - 1) 51 undoSteps++; 52 redoSteps = 0; 53 SelectObject(hDrawingDC, hBms[currInd]); 54 imageSaved = FALSE; 55 } 56 57 void ImageModel::Undo() 58 { 59 if (undoSteps > 0) 60 { 61 int oldWidth = GetWidth(); 62 int oldHeight = GetHeight(); 63 selectionWindow.ShowWindow(SW_HIDE); 64 currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE; 65 SelectObject(hDrawingDC, hBms[currInd]); 66 undoSteps--; 67 if (redoSteps < HISTORYSIZE - 1) 68 redoSteps++; 69 if (GetWidth() != oldWidth || GetHeight() != oldHeight) 70 NotifyDimensionsChanged(); 71 NotifyImageChanged(); 72 } 73 } 74 75 void ImageModel::Redo() 76 { 77 if (redoSteps > 0) 78 { 79 int oldWidth = GetWidth(); 80 int oldHeight = GetHeight(); 81 selectionWindow.ShowWindow(SW_HIDE); 82 currInd = (currInd + 1) % HISTORYSIZE; 83 SelectObject(hDrawingDC, hBms[currInd]); 84 redoSteps--; 85 if (undoSteps < HISTORYSIZE - 1) 86 undoSteps++; 87 if (GetWidth() != oldWidth || GetHeight() != oldHeight) 88 NotifyDimensionsChanged(); 89 NotifyImageChanged(); 90 } 91 } 92 93 void ImageModel::ResetToPrevious() 94 { 95 DeleteObject(hBms[currInd]); 96 hBms[currInd] = 97 (HBITMAP) CopyImage(hBms[(currInd + HISTORYSIZE - 1) % HISTORYSIZE], IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG); 98 SelectObject(hDrawingDC, hBms[currInd]); 99 NotifyImageChanged(); 100 } 101 102 void ImageModel::ClearHistory() 103 { 104 undoSteps = 0; 105 redoSteps = 0; 106 } 107 108 void ImageModel::Insert(HBITMAP hbm) 109 { 110 int oldWidth = GetWidth(); 111 int oldHeight = GetHeight(); 112 DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]); 113 hBms[(currInd + 1) % HISTORYSIZE] = hbm; 114 currInd = (currInd + 1) % HISTORYSIZE; 115 if (undoSteps < HISTORYSIZE - 1) 116 undoSteps++; 117 redoSteps = 0; 118 SelectObject(hDrawingDC, hBms[currInd]); 119 if (GetWidth() != oldWidth || GetHeight() != oldHeight) 120 NotifyDimensionsChanged(); 121 NotifyImageChanged(); 122 } 123 124 void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY) 125 { 126 HDC hdc; 127 HPEN oldPen; 128 HBRUSH oldBrush; 129 int oldWidth = GetWidth(); 130 int oldHeight = GetHeight(); 131 132 if (nWidth <= 0) 133 nWidth = 1; 134 if (nHeight <= 0) 135 nHeight = 1; 136 137 SelectObject(hDrawingDC, hBms[currInd]); 138 DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]); 139 hBms[(currInd + 1) % HISTORYSIZE] = CreateDIBWithProperties(nWidth, nHeight); 140 currInd = (currInd + 1) % HISTORYSIZE; 141 if (undoSteps < HISTORYSIZE - 1) 142 undoSteps++; 143 redoSteps = 0; 144 145 hdc = CreateCompatibleDC(hDrawingDC); 146 SelectObject(hdc, hBms[currInd]); 147 148 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, paletteModel.GetBgColor())); 149 oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(paletteModel.GetBgColor())); 150 Rectangle(hdc, 0, 0, nWidth, nHeight); 151 BitBlt(hdc, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), hDrawingDC, 0, 0, SRCCOPY); 152 DeleteObject(SelectObject(hdc, oldBrush)); 153 DeleteObject(SelectObject(hdc, oldPen)); 154 DeleteDC(hdc); 155 SelectObject(hDrawingDC, hBms[currInd]); 156 157 if (GetWidth() != oldWidth || GetHeight() != oldHeight) 158 NotifyDimensionsChanged(); 159 NotifyImageChanged(); 160 } 161 162 void ImageModel::SaveImage(LPTSTR lpFileName) 163 { 164 SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC); 165 } 166 167 BOOL ImageModel::IsImageSaved() 168 { 169 return imageSaved; 170 } 171 172 BOOL ImageModel::HasUndoSteps() 173 { 174 return undoSteps > 0; 175 } 176 177 BOOL ImageModel::HasRedoSteps() 178 { 179 return redoSteps > 0; 180 } 181 182 void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY) 183 { 184 int oldWidth = GetWidth(); 185 int oldHeight = GetHeight(); 186 Insert((HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP, 187 GetWidth() * nStretchPercentX / 100, 188 GetHeight() * nStretchPercentY / 100, 0)); 189 if (GetWidth() != oldWidth || GetHeight() != oldHeight) 190 NotifyDimensionsChanged(); 191 NotifyImageChanged(); 192 } 193 194 int ImageModel::GetWidth() 195 { 196 return GetDIBWidth(hBms[currInd]); 197 } 198 199 int ImageModel::GetHeight() 200 { 201 return GetDIBHeight(hBms[currInd]); 202 } 203 204 void ImageModel::InvertColors() 205 { 206 RECT rect = {0, 0, GetWidth(), GetHeight()}; 207 CopyPrevious(); 208 InvertRect(hDrawingDC, &rect); 209 NotifyImageChanged(); 210 } 211 212 void ImageModel::Clear(COLORREF color) 213 { 214 Rectangle(hDrawingDC, 0 - 1, 0 - 1, GetWidth() + 1, GetHeight() + 1); 215 NotifyImageChanged(); 216 } 217 218 HDC ImageModel::GetDC() 219 { 220 return hDrawingDC; 221 } 222 223 void ImageModel::FlipHorizontally() 224 { 225 CopyPrevious(); 226 StretchBlt(hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0, 227 GetWidth(), GetHeight(), SRCCOPY); 228 NotifyImageChanged(); 229 } 230 231 void ImageModel::FlipVertically() 232 { 233 CopyPrevious(); 234 StretchBlt(hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0, 235 GetWidth(), GetHeight(), SRCCOPY); 236 NotifyImageChanged(); 237 } 238 239 void ImageModel::RotateNTimes90Degrees(int iN) 240 { 241 if (iN == 2) 242 { 243 CopyPrevious(); 244 StretchBlt(hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), GetDC(), 245 0, 0, GetWidth(), GetHeight(), SRCCOPY); 246 } 247 NotifyImageChanged(); 248 } 249