ReactOS 0.4.15-dev-7842-g558ab78
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 return;
134 }
135
137}
138
140{
141 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
142
143 if (hbm == NULL)
144 {
146 return;
147 }
148
150 part.clear();
151 part.m_hbmImage = m_hbmMaster;
154
155 PushDone();
156}
157
158void ImageModel::PushImageForUndo(const RECT& rcPartial)
159{
160 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
161
163 part.clear();
164 part.m_bPartial = TRUE;
165 part.m_rcPart = rcPartial;
166
167 CRect rcImage = { 0, 0, GetWidth(), GetHeight() };
168 CRect& rc = part.m_rcPart;
169 if (!rc.IntersectRect(rc, rcImage))
170 rc.SetRect(-1, -1, 0, 0);
171
172 HBITMAP hbmMaster = LockBitmap();
173 part.m_hbmImage = getSubImage(hbmMaster, rc);
174 UnlockBitmap(hbmMaster);
175
176 PushDone();
177}
178
180{
181 m_currInd = (m_currInd + 1) % HISTORYSIZE; // Go next
182
183 if (m_undoSteps < HISTORYSIZE - 1)
184 m_undoSteps++;
185 m_redoSteps = 0;
186
189}
190
191void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
192{
193 // We cannot create bitmaps of size zero
194 if (nWidth <= 0)
195 nWidth = 1;
196 if (nHeight <= 0)
197 nHeight = 1;
198
199 // Create a white HBITMAP
200 HBITMAP hbmNew = CreateColorDIB(nWidth, nHeight, RGB(255, 255, 255));
201 if (!hbmNew)
202 {
204 return;
205 }
206
207 // Put the master image as a sub-image
208 RECT rcPart = { -nOffsetX, -nOffsetY, GetWidth() - nOffsetX, GetHeight() - nOffsetY };
209 HBITMAP hbmOld = imageModel.LockBitmap();
210 putSubImage(hbmNew, rcPart, hbmOld);
211 imageModel.UnlockBitmap(hbmOld);
212
213 // Push it
214 PushImageForUndo(hbmNew);
215
217}
218
220{
222}
223
225{
226 return g_imageSaved;
227}
228
229void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
230{
231 int oldWidth = GetWidth();
232 int oldHeight = GetHeight();
233 INT newWidth = oldWidth * nStretchPercentX / 100;
234 INT newHeight = oldHeight * nStretchPercentY / 100;
235 if (oldWidth != newWidth || oldHeight != newHeight)
236 {
237 HBITMAP hbm0 = CopyDIBImage(m_hbmMaster, newWidth, newHeight);
238 PushImageForUndo(hbm0);
239 }
240 if (nSkewDegX)
241 {
242 HBITMAP hbm1 = SkewDIB(m_hDrawingDC, m_hbmMaster, nSkewDegX, FALSE);
243 PushImageForUndo(hbm1);
244 }
245 if (nSkewDegY)
246 {
247 HBITMAP hbm2 = SkewDIB(m_hDrawingDC, m_hbmMaster, nSkewDegY, TRUE);
248 PushImageForUndo(hbm2);
249 }
251}
252
254{
255 return GetDIBWidth(m_hbmMaster);
256}
257
259{
261}
262
264{
265 RECT rect = {0, 0, GetWidth(), GetHeight()};
269}
270
272{
273 return m_hDrawingDC;
274}
275
277{
279 StretchBlt(m_hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
282}
283
285{
287 StretchBlt(m_hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
290}
291
293{
294 switch (iN)
295 {
296 case 1:
297 case 3:
298 {
301 break;
302 }
303 case 2:
304 {
308 break;
309 }
310 }
312}
313
315{
316 pt.x = max(0, min(pt.x, GetWidth()));
317 pt.y = max(0, min(pt.y, GetHeight()));
318}
319
321{
325 return ret;
326}
327
329{
331 BOOL bBlackAndWhite = IsBitmapBlackAndWhite(hBitmap);
333 return bBlackAndWhite;
334}
335
337{
341
342 PushImageForUndo(hNewBitmap);
343}
344
346{
347 // NOTE: An app cannot select a bitmap into more than one device context at a time.
348 ::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
349 HBITMAP hbmLocked = m_hbmMaster;
351 return hbmLocked;
352}
353
355{
356 m_hbmMaster = hbmLocked;
358}
#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:213
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:320
void SwapPart()
Definition: history.cpp:57
int m_undoSteps
Definition: history.h:59
int GetWidth() const
Definition: history.cpp:253
HBITMAP LockBitmap()
Definition: history.cpp:345
BOOL CanUndo() const
Definition: history.h:29
void FlipVertically()
Definition: history.cpp:284
void FlipHorizontally()
Definition: history.cpp:276
BOOL CanRedo() const
Definition: history.h:30
void PushBlackAndWhite()
Definition: history.cpp:336
HGDIOBJ m_hbmOld
Definition: history.h:62
int m_redoSteps
Definition: history.h:60
ImageModel()
Definition: history.cpp:35
void InvertColors()
Definition: history.cpp:263
BOOL IsImageSaved() const
Definition: history.cpp:224
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:292
void Crop(int nWidth, int nHeight, int nOffsetX=0, int nOffsetY=0)
Definition: history.cpp:191
void UnlockBitmap(HBITMAP hbmLocked)
Definition: history.cpp:354
int GetHeight() const
Definition: history.cpp:258
void PushDone()
Definition: history.cpp:179
HDC GetDC()
Definition: history.cpp:271
void Clamp(POINT &pt) const
Definition: history.cpp:314
void SaveImage(LPCWSTR lpFileName)
Definition: history.cpp:219
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:229
BOOL IsBlackAndWhite()
Definition: history.cpp:328
void putSubImage(HBITMAP hbmWhole, const RECT &rcPartial, HBITMAP hbmPart)
Definition: dib.cpp:428
BOOL SaveDIBToFile(HBITMAP hBitmap, LPCWSTR FileName, BOOL fIsMainFile, REFGUID guidFileType)
Definition: dib.cpp:151
HBITMAP getSubImage(HBITMAP hbmWhole, const RECT &rcPartial)
Definition: dib.cpp:409
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono)
Definition: dib.cpp:351
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono)
Definition: dib.cpp:312
HBITMAP ConvertToBlackAndWhite(HBITMAP hbm)
Definition: dib.cpp:631
int GetDIBHeight(HBITMAP hBitmap)
Definition: dib.cpp:144
BOOL IsBitmapBlackAndWhite(HBITMAP hbm)
Definition: dib.cpp:580
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:92
#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:1712
_In_ LPCSTR lpFileName
Definition: winbase.h:3071
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
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