ReactOS 0.4.15-dev-6680-g8c76870
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{
17 if (canvasWindow.IsWindow())
18 canvasWindow.Invalidate(FALSE);
19 if (miniature.IsWindow())
20 miniature.Invalidate(FALSE);
21}
22
24 : m_hDrawingDC(::CreateCompatibleDC(NULL))
25 , m_currInd(0)
26 , m_undoSteps(0)
27 , m_redoSteps(0)
28{
29 ZeroMemory(m_hBms, sizeof(m_hBms));
30
31 m_hBms[0] = CreateColorDIB(1, 1, RGB(255, 255, 255));
33
35}
36
38{
40
41 for (size_t i = 0; i < HISTORYSIZE; ++i)
42 {
43 if (m_hBms[i])
45 }
46}
47
48void ImageModel::Undo(BOOL bClearRedo)
49{
50 ATLTRACE("%s: %d\n", __FUNCTION__, m_undoSteps);
51 if (!CanUndo())
52 return;
53
55
56 // Select previous item
59
61 if (bClearRedo)
62 m_redoSteps = 0;
63 else if (m_redoSteps < HISTORYSIZE - 1)
65
67}
68
70{
71 ATLTRACE("%s: %d\n", __FUNCTION__, m_redoSteps);
72 if (!CanRedo())
73 return;
74
76
77 // Select next item
80
82 if (m_undoSteps < HISTORYSIZE - 1)
84
86}
87
89{
90 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
91
92 // Revert current item with previous item
96
98}
99
101{
102 m_undoSteps = 0;
103 m_redoSteps = 0;
104}
105
107{
108 ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
109
110 // Go to the next item with an HBITMAP or current item
115
116 if (m_undoSteps < HISTORYSIZE - 1)
117 m_undoSteps++;
118 m_redoSteps = 0;
119
122}
123
124void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
125{
126 // We cannot create bitmaps of size zero
127 if (nWidth <= 0)
128 nWidth = 1;
129 if (nHeight <= 0)
130 nHeight = 1;
131
132 // Create an HBITMAP
133 HBITMAP hbmCropped = CreateDIBWithProperties(nWidth, nHeight);
134 if (!hbmCropped)
135 return;
136
137 // Select the HBITMAP by memory DC
139 HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmCropped);
140
141 // Fill background of the HBITMAP
142 RECT rcBack = { 0, 0, nWidth, nHeight };
143 HBRUSH hbrBack = ::CreateSolidBrush(paletteModel.GetBgColor());
144 ::FillRect(hdcMem, &rcBack, hbrBack);
145 ::DeleteObject(hbrBack);
146
147 // Copy the old content
148 ::BitBlt(hdcMem, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), m_hDrawingDC, 0, 0, SRCCOPY);
149
150 // Clean up
151 ::SelectObject(hdcMem, hbmOld);
153
154 // Push it
155 PushImageForUndo(hbmCropped);
156
158}
159
161{
163}
164
166{
167 return g_imageSaved;
168}
169
170void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
171{
172 int oldWidth = GetWidth();
173 int oldHeight = GetHeight();
174 INT newWidth = oldWidth * nStretchPercentX / 100;
175 INT newHeight = oldHeight * nStretchPercentY / 100;
176 if (oldWidth != newWidth || oldHeight != newHeight)
177 {
178 HBITMAP hbm0 = CopyDIBImage(m_hBms[m_currInd], newWidth, newHeight);
179 PushImageForUndo(hbm0);
180 }
181 if (nSkewDegX)
182 {
183 HBITMAP hbm1 = SkewDIB(m_hDrawingDC, m_hBms[m_currInd], nSkewDegX, FALSE);
184 PushImageForUndo(hbm1);
185 }
186 if (nSkewDegY)
187 {
188 HBITMAP hbm2 = SkewDIB(m_hDrawingDC, m_hBms[m_currInd], nSkewDegY, TRUE);
189 PushImageForUndo(hbm2);
190 }
192}
193
195{
197}
198
200{
202}
203
205{
206 RECT rect = {0, 0, GetWidth(), GetHeight()};
210}
211
213{
214 return m_hDrawingDC;
215}
216
218{
220 StretchBlt(m_hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
223}
224
226{
228 StretchBlt(m_hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
231}
232
234{
235 switch (iN)
236 {
237 case 1:
238 case 3:
239 {
241 if (hbm)
243 break;
244 }
245 case 2:
246 {
250 break;
251 }
252 }
254}
255
257{
258 pt.x = max(0, min(pt.x, GetWidth()));
259 pt.y = max(0, min(pt.y, GetHeight()));
260}
261
263{
267 return ret;
268}
269
271{
273 BOOL bBlackAndWhite = IsBitmapBlackAndWhite(hBitmap);
275 return bBlackAndWhite;
276}
277
279{
283
284 if (hNewBitmap)
285 PushImageForUndo(hNewBitmap);
286}
287
289{
290 // NOTE: An app cannot select a bitmap into more than one device context at a time.
291 ::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
292 HBITMAP hbmLocked = m_hBms[m_currInd];
294 return hbmLocked;
295}
296
298{
299 m_hBms[m_currInd] = hbmLocked;
300 m_hbmOld = ::SelectObject(m_hDrawingDC, hbmLocked); // Re-select
301}
302
304{
306 return;
307
308 if (bUndoable)
310
314}
#define ATLTRACE(format,...)
Definition: atltrace.h:276
static HBITMAP CopyDIBImage(HBITMAP hbm, INT cx=0, INT cy=0)
Definition: dib.h:19
#define HISTORYSIZE
Definition: history.h:11
CCanvasWindow canvasWindow
Definition: canvas.cpp:10
HBITMAP CopyBitmap()
Definition: history.cpp:262
void ResetToPrevious(void)
Definition: history.cpp:88
int m_undoSteps
Definition: history.h:49
int GetWidth() const
Definition: history.cpp:194
void SaveImage(LPCTSTR lpFileName)
Definition: history.cpp:160
HBITMAP LockBitmap()
Definition: history.cpp:288
BOOL CanUndo() const
Definition: history.h:20
void FlipVertically()
Definition: history.cpp:225
void FlipHorizontally()
Definition: history.cpp:217
BOOL CanRedo() const
Definition: history.h:21
void PushBlackAndWhite()
Definition: history.cpp:278
HGDIOBJ m_hbmOld
Definition: history.h:52
int m_redoSteps
Definition: history.h:50
ImageModel()
Definition: history.cpp:23
void InvertColors()
Definition: history.cpp:204
BOOL IsImageSaved() const
Definition: history.cpp:165
void Redo(void)
Definition: history.cpp:69
void Undo(BOOL bClearRedo=FALSE)
Definition: history.cpp:48
void NotifyImageChanged()
Definition: history.cpp:15
virtual ~ImageModel()
Definition: history.cpp:37
int m_currInd
Definition: history.h:48
void RotateNTimes90Degrees(int iN)
Definition: history.cpp:233
void Crop(int nWidth, int nHeight, int nOffsetX=0, int nOffsetY=0)
Definition: history.cpp:124
void UnlockBitmap(HBITMAP hbmLocked)
Definition: history.cpp:297
int GetHeight() const
Definition: history.cpp:199
HDC GetDC()
Definition: history.cpp:212
HBITMAP m_hBms[HISTORYSIZE]
Definition: history.h:51
void Clamp(POINT &pt) const
Definition: history.cpp:256
void PushImageForUndo(HBITMAP hbm=NULL)
Definition: history.cpp:106
void SelectionClone(BOOL bUndoable=TRUE)
Definition: history.cpp:303
HDC m_hDrawingDC
Definition: history.h:47
void ClearHistory(void)
Definition: history.cpp:100
void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX=0, int nSkewDegY=0)
Definition: history.cpp:170
BOOL IsBlackAndWhite()
Definition: history.cpp:270
COLORREF GetBgColor() const
void DrawSelection(HDC hDCImage, COLORREF crBg=0, BOOL bBgTransparent=FALSE)
BOOL IsBackgroundTransparent() const
Definition: toolsmodel.cpp:207
HBITMAP CreateDIBWithProperties(int width, int height)
Definition: dib.cpp:32
BOOL SaveDIBToFile(HBITMAP hBitmap, LPCWSTR FileName, BOOL fIsMainFile, REFGUID guidFileType)
Definition: dib.cpp:151
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono)
Definition: dib.cpp:341
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono)
Definition: dib.cpp:302
HBITMAP ConvertToBlackAndWhite(HBITMAP hbm)
Definition: dib.cpp:588
int GetDIBHeight(HBITMAP hBitmap)
Definition: dib.cpp:144
BOOL IsBitmapBlackAndWhite(HBITMAP hbm)
Definition: dib.cpp:537
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
static VOID NTAPI BitBlt(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_reads_bytes_(Delta *Height) PUCHAR Buffer, _In_ ULONG BitsPerPixel, _In_ ULONG Delta)
Definition: common.c:49
#define RGB(r, g, b)
Definition: precomp.h:62
#define __FUNCTION__
Definition: types.h:116
unsigned int BOOL
Definition: ntddk_ex.h:94
pKey DeleteObject()
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
ToolsModel toolsModel
Definition: toolsmodel.cpp:10
CMiniatureWindow miniature
Definition: miniature.cpp:12
BOOL g_imageSaved
Definition: main.cpp:19
SelectionModel selectionModel
PaletteModel paletteModel
ImageModel imageModel
Definition: history.cpp:11
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
#define max(a, b)
Definition: svc.c:63
int32_t INT
Definition: typedefs.h:58
int ret
HDC hdcMem
Definition: welcome.c:104
#define ZeroMemory
Definition: winbase.h:1700
_In_ LPCSTR lpFileName
Definition: winbase.h:3061
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
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
BOOL WINAPI DeleteDC(_In_ HDC)
BOOL WINAPI InvertRect(_In_ HDC, _In_ LPCRECT)
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
const CHAR * LPCTSTR
Definition: xmlstorage.h:193