1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2023 - TortoiseGit
4 // Copyright (C) 2003-2006, 2009-2010, 2012-2013 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "WaterEffect.h"
25 CWaterEffect::CWaterEffect()
29 CWaterEffect::~CWaterEffect()
33 void CWaterEffect::Create(int iWidth
, int iHeight
)
35 m_iBuffer1
.reset (new int[iWidth
*iHeight
]);
36 m_iBuffer2
.reset (new int[iWidth
*iHeight
]);
46 void CWaterEffect::Blob(int x
, int y
, int radius
, int height
, int page
)
51 pNew
= m_iBuffer1
.get();
53 pNew
= m_iBuffer2
.get();
56 x
= 1 + radius
+ rand() % (m_iWidth
- 2 * radius
- 1);
58 y
= 1 + radius
+ rand() % (m_iHeight
- 2 * radius
- 1);
70 if (x
+ radius
> m_iWidth
-1)
71 right
-= (x
+radius
-m_iWidth
+1);
72 if (y
+ radius
> m_iHeight
-1)
73 bottom
-= (y
+radius
-m_iHeight
+1);
75 const int rquad
= radius
* radius
;
76 for(int cy
= top
; cy
< bottom
; cy
++)
78 const int cyq
= cy
*cy
;
79 for(int cx
= left
; cx
< right
; cx
++)
81 if (cx
*cx
+ cyq
< rquad
)
82 pNew
[m_iWidth
*(cy
+y
) + (cx
+x
)] += height
;
87 void CWaterEffect::ClearWater()
89 // clear height fields
90 SecureZeroMemory(m_iBuffer1
.get(), (m_iWidth
*m_iHeight
)*sizeof(int));
91 SecureZeroMemory(m_iBuffer2
.get(), (m_iWidth
*m_iHeight
)*sizeof(int));
94 void CWaterEffect::Render(DWORD
* pSrcImage
, DWORD
* pTargetImage
)
96 DrawWater(m_iHpage
, m_iLightModifier
, pSrcImage
, pTargetImage
);
98 CalcWater(m_iHpage
, m_iDensity
);
100 //change the field from 0 to 1 and vice versa
104 void CWaterEffect::CalcWater(int npage
, int density
)
111 pNew
= m_iBuffer1
.get();
112 pOld
= m_iBuffer2
.get();
116 pNew
= m_iBuffer2
.get();
117 pOld
= m_iBuffer1
.get();
120 // a description of the algorithm and an implementation
121 // in 'pseudocode' can be found here:
122 // http://freespace.virgin.net/hugo.elias/graphics/x_water.htm
123 int count
= m_iWidth
+ 1;
124 for (int y
= (m_iHeight
-1)*m_iWidth
; count
< y
; count
+= 2)
126 for (int x
= count
+m_iWidth
-2; count
< x
; count
++)
129 const int newh
= ((pOld
[count
+ m_iWidth
]
130 + pOld
[count
- m_iWidth
]
133 + pOld
[count
- m_iWidth
- 1]
134 + pOld
[count
- m_iWidth
+ 1]
135 + pOld
[count
+ m_iWidth
- 1]
136 + pOld
[count
+ m_iWidth
+ 1]
140 pNew
[count
] = newh
- (newh
>> density
);
145 void CWaterEffect::SmoothWater(int npage
)
147 //flatten and spread the waves
153 pNew
= m_iBuffer1
.get();
154 pOld
= m_iBuffer2
.get();
158 pNew
= m_iBuffer2
.get();
159 pOld
= m_iBuffer1
.get();
162 // a description of the algorithm and an implementation
163 // in 'pseudocode' can be found here:
164 // http://freespace.virgin.net/hugo.elias/graphics/x_water.htm
165 int count
= m_iWidth
+ 1;
166 for(int y
=1; y
<m_iHeight
-1; y
++)
168 for(int x
=1; x
<m_iWidth
-1; x
++)
170 const int newh
= ((pOld
[count
+ m_iWidth
]
171 + pOld
[count
- m_iWidth
]
174 + pOld
[count
- m_iWidth
- 1]
175 + pOld
[count
- m_iWidth
+ 1]
176 + pOld
[count
+ m_iWidth
- 1]
177 + pOld
[count
+ m_iWidth
+ 1]
181 pNew
[count
] = newh
>>1;
188 void CWaterEffect::DrawWater(int /*page*/, int /*LightModifier*/, DWORD
* pSrcImage
, DWORD
* pTargetImage
)
194 int offset
= m_iWidth
+ 1;
196 long lBreak
= m_iWidth
*m_iHeight
;
198 int *ptr
= m_iBuffer1
.get();
201 for (y
= (m_iHeight
-1)*m_iWidth
; offset
< y
; offset
+= 2)
203 for (x
= offset
+ m_iWidth
- 2; offset
< x
; offset
++)
205 dx
= ptr
[offset
] - ptr
[offset
+1];
206 dy
= ptr
[offset
] - ptr
[offset
+m_iWidth
];
208 lIndex
= offset
+ m_iWidth
*(dy
>>3) + (dx
>>3);
209 if (lIndex
< lBreak
&& lIndex
> 0)
211 c
= pSrcImage
[lIndex
];
212 c
= GetShiftedColor(c
,dx
);
213 pTargetImage
[offset
] = c
;
217 dx
= ptr
[offset
] - ptr
[offset
+1];
218 dy
= ptr
[offset
] - ptr
[offset
+m_iWidth
];
220 lIndex
= offset
+ m_iWidth
*(dy
>>3) + (dx
>>3);
221 if (lIndex
< lBreak
&& lIndex
> 0)
223 c
= pSrcImage
[lIndex
];
224 c
= GetShiftedColor(c
,dx
);
225 pTargetImage
[offset
] = c
;
231 COLORREF
CWaterEffect::GetShiftedColor(COLORREF color
, int shift
)
233 const long R
= GetRValue(color
)-shift
;
234 const long G
= GetGValue(color
)-shift
;
235 const long B
= GetBValue(color
)-shift
;
237 const int ir
= NormalizeColor(R
);
238 const int ig
= NormalizeColor(G
);
239 const int ib
= NormalizeColor(B
);
241 return RGB(ir
,ig
,ib
);
244 int CWaterEffect::NormalizeColor(long color
) const