Minor cleanup
[TortoiseGit.git] / src / Utils / MiscUI / WaterEffect.cpp
blobeb87874c8ff6f71545833dd2d29f7af5bce62903
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2006 - Stefan Kueng
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "WaterEffect.h"
22 #include <math.h>
25 CWaterEffect::CWaterEffect()
27 m_iBuffer1 = NULL;
28 m_iBuffer2 = NULL;
30 m_iWidth = 0;
31 m_iHeight = 0;
33 m_iLightModifier = 10;
34 m_iHpage = 0;
35 m_iDensity = 2;
38 CWaterEffect::~CWaterEffect()
40 // free memory
41 if (m_iBuffer1 != NULL)
42 delete [] m_iBuffer1;
43 if (m_iBuffer2 != NULL)
44 delete [] m_iBuffer2;
46 m_iBuffer1 = NULL;
47 m_iBuffer2 = NULL;
50 void CWaterEffect::Create(int iWidth, int iHeight)
52 if (m_iBuffer1 != NULL)
53 delete [] m_iBuffer1;
54 if (m_iBuffer2 != NULL)
55 delete [] m_iBuffer2;
57 m_iBuffer1 = new int[(iWidth*iHeight)];
58 m_iBuffer2 = new int[(iWidth*iHeight)];
60 m_iWidth = iWidth;
61 m_iHeight = iHeight;
63 ClearWater();
65 m_iHpage = 0;
69 void CWaterEffect::Blob(int x, int y, int radius, int height, int page)
71 int rquad;
72 int cx, cy, cyq;
73 int left, top, right, bottom;
75 int *pNew;
76 int *pOld;
78 if (page == 0)
80 pNew = &m_iBuffer1[0];
81 pOld = &m_iBuffer2[0];
83 else
85 pNew = &m_iBuffer2[0];
86 pOld = &m_iBuffer1[0];
89 rquad = radius * radius;
91 if (x<0)
92 x = 1 + radius + rand() % (m_iWidth - 2 * radius - 1);
93 if (y<0)
94 y = 1 + radius + rand() % (m_iHeight - 2 * radius - 1);
96 left = -radius;
97 right = radius;
98 top = -radius;
99 bottom = radius;
101 // clip edges
102 if (x - radius < 1)
103 left -= (x-radius-1);
104 if (y - radius < 1)
105 top -= (y-radius-1);
106 if (x + radius > m_iWidth-1)
107 right -= (x+radius-m_iWidth+1);
108 if (y + radius > m_iHeight-1)
109 bottom-= (y+radius-m_iHeight+1);
111 for(cy = top; cy < bottom; cy++)
113 cyq = cy*cy;
114 for(cx = left; cx < right; cx++)
116 if (cx*cx + cyq < rquad)
118 pNew[m_iWidth*(cy+y) + (cx+x)] += height;
124 void CWaterEffect::ClearWater()
126 // clear height fields
127 memset(m_iBuffer1,0, (m_iWidth*m_iHeight)*sizeof(int));
128 memset(m_iBuffer2,0, (m_iWidth*m_iHeight)*sizeof(int));
131 void CWaterEffect::Render(DWORD* pSrcImage, DWORD* pTargetImage)
133 DrawWater(m_iHpage, m_iLightModifier, pSrcImage, pTargetImage);
135 CalcWater(m_iHpage, m_iDensity);
137 //change the field from 0 to 1 and vice versa
138 m_iHpage ^= 1;
142 void CWaterEffect::CalcWater(int npage, int density)
144 int newh;
145 int count = m_iWidth + 1;
146 int *pNew;
147 int *pOld;
149 if (npage == 0)
151 pNew = &m_iBuffer1[0];
152 pOld = &m_iBuffer2[0];
154 else
156 pNew = &m_iBuffer2[0];
157 pOld = &m_iBuffer1[0];
160 int x, y;
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 for (y = (m_iHeight-1)*m_iWidth; count < y; count += 2)
167 for (x = count+m_iWidth-2; count < x; count++)
169 // use eight pixels
170 newh = ((pOld[count + m_iWidth]
171 + pOld[count - m_iWidth]
172 + pOld[count + 1]
173 + pOld[count - 1]
174 + pOld[count - m_iWidth - 1]
175 + pOld[count - m_iWidth + 1]
176 + pOld[count + m_iWidth - 1]
177 + pOld[count + m_iWidth + 1]
178 ) >> 2 )
179 - pNew[count];
181 pNew[count] = newh - (newh >> density);
186 void CWaterEffect::SmoothWater(int npage)
188 //flatten and spread the waves
189 int newh;
190 int count = m_iWidth + 1;
192 int *pNew;
193 int *pOld;
195 if (npage == 0)
197 pNew = &m_iBuffer1[0];
198 pOld = &m_iBuffer2[0];
200 else
202 pNew = &m_iBuffer2[0];
203 pOld = &m_iBuffer1[0];
206 int x, y;
208 // a description of the algorithm and an implementation
209 // in 'pseudocode' can be found here:
210 // http://freespace.virgin.net/hugo.elias/graphics/x_water.htm
211 for(y=1; y<m_iHeight-1; y++)
213 for(x=1; x<m_iWidth-1; x++)
215 newh = ((pOld[count + m_iWidth]
216 + pOld[count - m_iWidth]
217 + pOld[count + 1]
218 + pOld[count - 1]
219 + pOld[count - m_iWidth - 1]
220 + pOld[count - m_iWidth + 1]
221 + pOld[count + m_iWidth - 1]
222 + pOld[count + m_iWidth + 1]
223 ) >> 3 )
224 + pNew[count];
226 pNew[count] = newh>>1;
227 count++;
229 count += 2;
233 void CWaterEffect::DrawWater(int /*page*/, int /*LightModifier*/, DWORD* pSrcImage, DWORD* pTargetImage)
235 int dx, dy;
236 int x, y;
237 DWORD c;
239 int offset = m_iWidth + 1;
240 long lIndex;
241 long lBreak = m_iWidth*m_iHeight;
243 int *ptr = &m_iBuffer1[0];
246 for (y = (m_iHeight-1)*m_iWidth; offset < y; offset += 2)
248 for (x = offset + m_iWidth - 2; offset < x; offset++)
250 dx = ptr[offset] - ptr[offset+1];
251 dy = ptr[offset] - ptr[offset+m_iWidth];
253 lIndex = offset + m_iWidth*(dy>>3) + (dx>>3);
254 if (lIndex < lBreak && lIndex > 0)
256 c = pSrcImage[lIndex];
257 c = GetShiftedColor(c,dx);
258 pTargetImage[offset] = c;
261 offset++;
262 dx = ptr[offset] - ptr[offset+1];
263 dy = ptr[offset] - ptr[offset+m_iWidth];
265 lIndex = offset + m_iWidth*(dy>>3) + (dx>>3);
266 if (lIndex < lBreak && lIndex > 0)
268 c = pSrcImage[lIndex];
269 c = GetShiftedColor(c,dx);
270 pTargetImage[offset] = c;
276 COLORREF CWaterEffect::GetShiftedColor(COLORREF color, int shift)
278 long R;
279 long G;
280 long B;
281 int ir;
282 int ig;
283 int ib;
285 R = GetRValue(color)-shift;
286 G = GetGValue(color)-shift;
287 B = GetBValue(color)-shift;
289 ir = (R < 0) ? 0 : (R > 255) ? 255 : R;
290 ig = (G < 0) ? 0 : (G > 255) ? 255 : G;
291 ib = (B < 0) ? 0 : (B > 255) ? 255 : B;
293 return RGB(ir,ig,ib);