ReactOS 0.4.16-dev-2491-g3dc6630
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{
41 m_hbmMaster = CreateColorDIB(1, 1, RGB(255, 255, 255));
43
45}
46
48{
53}
54
56{
58 if (!part.m_bPartial)
59 {
61 return;
62 }
63
64 HBITMAP hbmMaster = LockBitmap();
65 HBITMAP hbmPart = getSubImage(hbmMaster, part.m_rcPart);
66 putSubImage(hbmMaster, part.m_rcPart, part.m_hbmImage);
68 part.m_hbmImage = hbmPart;
69 UnlockBitmap(hbmMaster);
70}
71
72void ImageModel::Undo(BOOL bClearRedo)
73{
74 ATLTRACE("%s: %d\n", __FUNCTION__, m_undoSteps);
75 if (!CanUndo())
76 return;
77
79
80 m_currInd = (m_currInd + HISTORYSIZE - 1) % HISTORYSIZE; // Go previous
82 SwapPart();
84
86 if (bClearRedo)
87 m_redoSteps = 0;
88 else if (m_redoSteps < HISTORYSIZE - 1)
90
92}
93
95{
96 ATLTRACE("%s: %d\n", __FUNCTION__, m_redoSteps);
97 if (!CanRedo())
98 return;
99
101
103 SwapPart();
104 m_currInd = (m_currInd + 1) % HISTORYSIZE; // Go next
106
107 m_redoSteps--;
108 if (m_undoSteps < HISTORYSIZE - 1)
109 m_undoSteps++;
110
112}
113
115{
116 for (int i = 0; i < HISTORYSIZE; ++i)
117 {
119 }
120
121 m_undoSteps = 0;
122 m_redoSteps = 0;
123}
124
126{
128 if (hbm == NULL)
129 {
131 ClearHistory();
132 return;
133 }
134
136}
137
139{
140 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
141
142 if (hbm == NULL)
143 {
145 ClearHistory();
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 ClearHistory();
205 return;
206 }
207
208 // Put the master image as a sub-image
209 RECT rcPart = { -nOffsetX, -nOffsetY, GetWidth() - nOffsetX, GetHeight() - nOffsetY };
210 HBITMAP hbmOld = imageModel.LockBitmap();
211 putSubImage(hbmNew, rcPart, hbmOld);
212 imageModel.UnlockBitmap(hbmOld);
213
214 // Push it
215 PushImageForUndo(hbmNew);
216
218}
219
221{
223}
224
226{
227 return g_imageSaved;
228}
229
230void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
231{
232 int oldWidth = GetWidth();
233 int oldHeight = GetHeight();
234 INT newWidth = oldWidth * nStretchPercentX / 100;
235 INT newHeight = oldHeight * nStretchPercentY / 100;
236 if (oldWidth != newWidth || oldHeight != newHeight)
237 {
238 HBITMAP hbm0 = CopyDIBImage(m_hbmMaster, newWidth, newHeight);
239 PushImageForUndo(hbm0);
240 }
241 if (nSkewDegX)
242 {
243 HBITMAP hbm1 = SkewDIB(m_hDrawingDC, m_hbmMaster, nSkewDegX, FALSE);
244 PushImageForUndo(hbm1);
245 }
246 if (nSkewDegY)
247 {
248 HBITMAP hbm2 = SkewDIB(m_hDrawingDC, m_hbmMaster, nSkewDegY, TRUE);
249 PushImageForUndo(hbm2);
250 }
252}
253
255{
256 return GetDIBWidth(m_hbmMaster);
257}
258
260{
262}
263
265{
266 RECT rect = {0, 0, GetWidth(), GetHeight()};
270}
271
273{
274 return m_hDrawingDC;
275}
276
278{
280 StretchBlt(m_hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
283}
284
286{
288 StretchBlt(m_hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
291}
292
294{
295 switch (iN)
296 {
297 case 1:
298 case 3:
299 {
302 break;
303 }
304 case 2:
305 {
309 break;
310 }
311 }
313}
314
316{
317 pt.x = max(0, min(pt.x, GetWidth()));
318 pt.y = max(0, min(pt.y, GetHeight()));
319}
320
322{
326 return ret;
327}
328
330{
332 BOOL bBlackAndWhite = IsBitmapBlackAndWhite(hBitmap);
334 return bBlackAndWhite;
335}
336
338{
342
343 PushImageForUndo(hNewBitmap);
344}
345
347{
348 // NOTE: An app cannot select a bitmap into more than one device context at a time.
349 ::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
350 HBITMAP hbmLocked = m_hbmMaster;
352 return hbmLocked;
353}
354
356{
357 m_hbmMaster = hbmLocked;
359}
#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:321
void SwapPart()
Definition: history.cpp:55
int m_undoSteps
Definition: history.h:59
int GetWidth() const
Definition: history.cpp:254
HBITMAP LockBitmap()
Definition: history.cpp:346
BOOL CanUndo() const
Definition: history.h:29
void FlipVertically()
Definition: history.cpp:285
void FlipHorizontally()
Definition: history.cpp:277
BOOL CanRedo() const
Definition: history.h:30
void PushBlackAndWhite()
Definition: history.cpp:337
HGDIOBJ m_hbmOld
Definition: history.h:62
int m_redoSteps
Definition: history.h:60
ImageModel()
Definition: history.cpp:35
void InvertColors()
Definition: history.cpp:264
BOOL IsImageSaved() const
Definition: history.cpp:225
void Redo(void)
Definition: history.cpp:94
void PushImageForUndo()
Definition: history.cpp:125
HBITMAP m_hbmMaster
Definition: history.h:57
void Undo(BOOL bClearRedo=FALSE)
Definition: history.cpp:72
void NotifyImageChanged()
Definition: history.cpp:23
virtual ~ImageModel()
Definition: history.cpp:47
int m_currInd
Definition: history.h:58
void RotateNTimes90Degrees(int iN)
Definition: history.cpp:293
void Crop(int nWidth, int nHeight, int nOffsetX=0, int nOffsetY=0)
Definition: history.cpp:191
void UnlockBitmap(HBITMAP hbmLocked)
Definition: history.cpp:355
int GetHeight() const
Definition: history.cpp:259
void PushDone()
Definition: history.cpp:179
HDC GetDC()
Definition: history.cpp:272
void Clamp(POINT &pt) const
Definition: history.cpp:315
void SaveImage(LPCWSTR lpFileName)
Definition: history.cpp:220
HDC m_hDrawingDC
Definition: history.h:56
void ClearHistory(void)
Definition: history.cpp:114
IMAGE_PART m_historyItems[HISTORYSIZE]
Definition: history.h:61
void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX=0, int nSkewDegY=0)
Definition: history.cpp:230
BOOL IsBlackAndWhite()
Definition: history.cpp:329
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:67
return ret
Definition: mutex.c:146
#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
_In_ LPCSTR lpFileName
Definition: winbase.h:2824
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