ReactOS 0.4.16-dev-979-g79f281e
history.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Undo and redo functionality
5 * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6 * Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9#include "precomp.h"
10
12
13/* FUNCTIONS ********************************************************/
14
16{
21}
22
24{
25 if (canvasWindow.IsWindow())
26 {
28 canvasWindow.Invalidate();
29 }
30
31 if (miniature.IsWindow())
32 miniature.Invalidate();
33}
34
36 : m_hDrawingDC(::CreateCompatibleDC(NULL))
37 , m_currInd(0)
38 , m_undoSteps(0)
39 , m_redoSteps(0)
40{
42
43 m_hbmMaster = CreateColorDIB(1, 1, RGB(255, 255, 255));
45
47}
48
50{
55}
56
58{
60 if (!part.m_bPartial)
61 {
63 return;
64 }
65
66 HBITMAP hbmMaster = LockBitmap();
67 HBITMAP hbmPart = getSubImage(hbmMaster, part.m_rcPart);
68 putSubImage(hbmMaster, part.m_rcPart, part.m_hbmImage);
70 part.m_hbmImage = hbmPart;
71 UnlockBitmap(hbmMaster);
72}
73
74void ImageModel::Undo(BOOL bClearRedo)
75{
76 ATLTRACE("%s: %d\n", __FUNCTION__, m_undoSteps);
77 if (!CanUndo())
78 return;
79
81
82 m_currInd = (m_currInd + HISTORYSIZE - 1) % HISTORYSIZE; // Go previous
84 SwapPart();
86
88 if (bClearRedo)
89 m_redoSteps = 0;
90 else if (m_redoSteps < HISTORYSIZE - 1)
92
94}
95
97{
98 ATLTRACE("%s: %d\n", __FUNCTION__, m_redoSteps);
99 if (!CanRedo())
100 return;
101
103
105 SwapPart();
106 m_currInd = (m_currInd + 1) % HISTORYSIZE; // Go next
108
109 m_redoSteps--;
110 if (m_undoSteps < HISTORYSIZE - 1)
111 m_undoSteps++;
112
114}
115
117{
118 for (int i = 0; i < HISTORYSIZE; ++i)
119 {
121 }
122
123 m_undoSteps = 0;
124 m_redoSteps = 0;
125}
126
128{
130 if (hbm == NULL)
131 {
133 ClearHistory();
134 return;
135 }
136
138}
139
141{
142 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
143
144 if (hbm == NULL)
145 {
147 ClearHistory();
148 return;
149 }
150
152 part.clear();
153 part.m_hbmImage = m_hbmMaster;
156
157 PushDone();
158}
159
160void ImageModel::PushImageForUndo(const RECT& rcPartial)
161{
162 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
163
165 part.clear();
166 part.m_bPartial = TRUE;
167 part.m_rcPart = rcPartial;
168
169 CRect rcImage = { 0, 0, GetWidth(), GetHeight() };
170 CRect& rc = part.m_rcPart;
171 if (!rc.IntersectRect(rc, rcImage))
172 rc.SetRect(-1, -1, 0, 0);
173
174 HBITMAP hbmMaster = LockBitmap();
175 part.m_hbmImage = getSubImage(hbmMaster, rc);
176 UnlockBitmap(hbmMaster);
177
178 PushDone();
179}
180
182{
183 m_currInd = (m_currInd + 1) % HISTORYSIZE; // Go next
184
185 if (m_undoSteps < HISTORYSIZE - 1)
186 m_undoSteps++;
187 m_redoSteps = 0;
188
191}
192
193void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
194{
195 // We cannot create bitmaps of size zero
196 if (nWidth <= 0)
197 nWidth = 1;
198 if (nHeight <= 0)
199 nHeight = 1;
200
201 // Create a white HBITMAP
202 HBITMAP hbmNew = CreateColorDIB(nWidth, nHeight, RGB(255, 255, 255));
203 if (!hbmNew)
204 {
206 ClearHistory();
207 return;
208 }
209
210 // Put the master image as a sub-image
211 RECT rcPart = { -nOffsetX, -nOffsetY, GetWidth() - nOffsetX, GetHeight() - nOffsetY };
212 HBITMAP hbmOld = imageModel.LockBitmap();
213 putSubImage(hbmNew, rcPart, hbmOld);
214 imageModel.UnlockBitmap(hbmOld);
215
216 // Push it
217 PushImageForUndo(hbmNew);
218
220}
221
223{
225}
226
228{
229 return g_imageSaved;
230}
231
232void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
233{
234 int oldWidth = GetWidth();
235 int oldHeight = GetHeight();
236 INT newWidth = oldWidth * nStretchPercentX / 100;
237 INT newHeight = oldHeight * nStretchPercentY / 100;
238 if (oldWidth != newWidth || oldHeight != newHeight)
239 {
240 HBITMAP hbm0 = CopyDIBImage(m_hbmMaster, newWidth, newHeight);
241 PushImageForUndo(hbm0);
242 }
243 if (nSkewDegX)
244 {
245 HBITMAP hbm1 = SkewDIB(m_hDrawingDC, m_hbmMaster, nSkewDegX, FALSE);
246 PushImageForUndo(hbm1);
247 }
248 if (nSkewDegY)
249 {
250 HBITMAP hbm2 = SkewDIB(m_hDrawingDC, m_hbmMaster, nSkewDegY, TRUE);
251 PushImageForUndo(hbm2);
252 }
254}
255
257{
258 return GetDIBWidth(m_hbmMaster);
259}
260
262{
264}
265
267{
268 RECT rect = {0, 0, GetWidth(), GetHeight()};
272}
273
275{
276 return m_hDrawingDC;
277}
278
280{
282 StretchBlt(m_hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
285}
286
288{
290 StretchBlt(m_hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
293}
294
296{
297 switch (iN)
298 {
299 case 1:
300 case 3:
301 {
304 break;
305 }
306 case 2:
307 {
311 break;
312 }
313 }
315}
316
318{
319 pt.x = max(0, min(pt.x, GetWidth()));
320 pt.y = max(0, min(pt.y, GetHeight()));
321}
322
324{
328 return ret;
329}
330
332{
334 BOOL bBlackAndWhite = IsBitmapBlackAndWhite(hBitmap);
336 return bBlackAndWhite;
337}
338
340{
344
345 PushImageForUndo(hNewBitmap);
346}
347
349{
350 // NOTE: An app cannot select a bitmap into more than one device context at a time.
351 ::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
352 HBITMAP hbmLocked = m_hbmMaster;
354 return hbmLocked;
355}
356
358{
359 m_hbmMaster = hbmLocked;
361}
#define ATLASSERT(x)
Definition: CComVariant.cpp:10
#define ATLTRACE(format,...)
Definition: atltrace.h:269
static HBITMAP CopyDIBImage(HBITMAP hbm, INT cx=0, INT cy=0)
Definition: dib.h:19
#define HISTORYSIZE
Definition: history.h:11
BOOL g_imageSaved
Definition: main.cpp:21
void ShowOutOfMemory(void)
Definition: main.cpp:34
SelectionModel selectionModel
CCanvasWindow canvasWindow
Definition: canvas.cpp:10
VOID updateScrollRange()
Definition: canvas.cpp:220
void SetRectEmpty() noexcept
Definition: atltypes.h:431
BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2) noexcept
Definition: atltypes.h:346
void SetRect(int x1, int y1, int x2, int y2) noexcept
Definition: atltypes.h:423
HBITMAP CopyBitmap()
Definition: history.cpp:323
void SwapPart()
Definition: history.cpp:57
int m_undoSteps
Definition: history.h:59
int GetWidth() const
Definition: history.cpp:256
HBITMAP LockBitmap()
Definition: history.cpp:348
BOOL CanUndo() const
Definition: history.h:29
void FlipVertically()
Definition: history.cpp:287
void FlipHorizontally()
Definition: history.cpp:279
BOOL CanRedo() const
Definition: history.h:30
void PushBlackAndWhite()
Definition: history.cpp:339
HGDIOBJ m_hbmOld
Definition: history.h:62
int m_redoSteps
Definition: history.h:60
ImageModel()
Definition: history.cpp:35
void InvertColors()
Definition: history.cpp:266
BOOL IsImageSaved() const
Definition: history.cpp:227
void Redo(void)
Definition: history.cpp:96
void PushImageForUndo()
Definition: history.cpp:127
HBITMAP m_hbmMaster
Definition: history.h:57
void Undo(BOOL bClearRedo=FALSE)
Definition: history.cpp:74
void NotifyImageChanged()
Definition: history.cpp:23
virtual ~ImageModel()
Definition: history.cpp:49
int m_currInd
Definition: history.h:58
void RotateNTimes90Degrees(int iN)
Definition: history.cpp:295
void Crop(int nWidth, int nHeight, int nOffsetX=0, int nOffsetY=0)
Definition: history.cpp:193
void UnlockBitmap(HBITMAP hbmLocked)
Definition: history.cpp:357
int GetHeight() const
Definition: history.cpp:261
void PushDone()
Definition: history.cpp:181
HDC GetDC()
Definition: history.cpp:274
void Clamp(POINT &pt) const
Definition: history.cpp:317
void SaveImage(LPCWSTR lpFileName)
Definition: history.cpp:222
HDC m_hDrawingDC
Definition: history.h:56
void ClearHistory(void)
Definition: history.cpp:116
IMAGE_PART m_historyItems[HISTORYSIZE]
Definition: history.h:61
void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX=0, int nSkewDegY=0)
Definition: history.cpp:232
BOOL IsBlackAndWhite()
Definition: history.cpp:331
void putSubImage(HBITMAP hbmWhole, const RECT &rcPartial, HBITMAP hbmPart)
Definition: dib.cpp:429
BOOL SaveDIBToFile(HBITMAP hBitmap, LPCWSTR FileName, BOOL fIsMainFile, REFGUID guidFileType)
Definition: dib.cpp:151
HBITMAP getSubImage(HBITMAP hbmWhole, const RECT &rcPartial)
Definition: dib.cpp:410
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono)
Definition: dib.cpp:352
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono)
Definition: dib.cpp:313
HBITMAP ConvertToBlackAndWhite(HBITMAP hbm)
Definition: dib.cpp:632
int GetDIBHeight(HBITMAP hBitmap)
Definition: dib.cpp:144
BOOL IsBitmapBlackAndWhite(HBITMAP hbm)
Definition: dib.cpp:581
HBITMAP CreateColorDIB(int width, int height, COLORREF rgb)
Definition: dib.cpp:65
int GetDIBWidth(HBITMAP hBitmap)
Definition: dib.cpp:136
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static HBITMAP hBitmap
Definition: timezone.c:26
#define pt(x, y)
Definition: drawing.c:79
#define RGB(r, g, b)
Definition: precomp.h:71
#define __FUNCTION__
Definition: types.h:116
unsigned int BOOL
Definition: ntddk_ex.h:94
pKey DeleteObject()
#define Swap(a, b)
Definition: geom.c:201
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ImageModel imageModel
Definition: history.cpp:11
CMiniatureWindow miniature
Definition: miniature.cpp:12
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
#define min(a, b)
Definition: monoChain.cc:55
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
& rect
Definition: startmenu.cpp:1413
CRect m_rcPart
Definition: history.h:15
HBITMAP m_hbmImage
Definition: history.h:16
void clear()
Definition: history.cpp:15
BOOL m_bPartial
Definition: history.h:17
#define max(a, b)
Definition: svc.c:63
int32_t INT
Definition: typedefs.h:58
int ret
#define ZeroMemory
Definition: winbase.h:1743
_In_ LPCSTR lpFileName
Definition: winbase.h:3102
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define SRCCOPY
Definition: wingdi.h:333
BOOL WINAPI DeleteDC(_In_ HDC)
BOOL WINAPI InvertRect(_In_ HDC, _In_ LPCRECT)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185