Fix piping to TortoiseGitUDiff by checking for ERROR_BROKEN_PIPE and treating that...
[TortoiseGit.git] / src / Utils / MiscUI / WaterEffect.cpp
blob104074fa329dc1d8c6f73bdf8318f68a487f5e14
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.
20 #include "stdafx.h"
21 #include "WaterEffect.h"
23 #include <math.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]);
38 m_iWidth = iWidth;
39 m_iHeight = iHeight;
41 ClearWater();
43 m_iHpage = 0;
46 void CWaterEffect::Blob(int x, int y, int radius, int height, int page)
48 int *pNew;
50 if (page == 0)
51 pNew = m_iBuffer1.get();
52 else
53 pNew = m_iBuffer2.get();
55 if (x<0)
56 x = 1 + radius + rand() % (m_iWidth - 2 * radius - 1);
57 if (y<0)
58 y = 1 + radius + rand() % (m_iHeight - 2 * radius - 1);
60 int left = -radius;
61 int right = radius;
62 int top = -radius;
63 int bottom = radius;
65 // clip edges
66 if (x - radius < 1)
67 left -= (x-radius-1);
68 if (y - radius < 1)
69 top -= (y-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
101 m_iHpage ^= 1;
104 void CWaterEffect::CalcWater(int npage, int density)
106 int *pNew;
107 int *pOld;
109 if (npage == 0)
111 pNew = m_iBuffer1.get();
112 pOld = m_iBuffer2.get();
114 else
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++)
128 // use eight pixels
129 const int newh = ((pOld[count + m_iWidth]
130 + pOld[count - m_iWidth]
131 + pOld[count + 1]
132 + pOld[count - 1]
133 + pOld[count - m_iWidth - 1]
134 + pOld[count - m_iWidth + 1]
135 + pOld[count + m_iWidth - 1]
136 + pOld[count + m_iWidth + 1]
137 ) >> 2 )
138 - pNew[count];
140 pNew[count] = newh - (newh >> density);
145 void CWaterEffect::SmoothWater(int npage)
147 //flatten and spread the waves
148 int *pNew;
149 int *pOld;
151 if (npage == 0)
153 pNew = m_iBuffer1.get();
154 pOld = m_iBuffer2.get();
156 else
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]
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 ) >> 3 )
179 + pNew[count];
181 pNew[count] = newh>>1;
182 count++;
184 count += 2;
188 void CWaterEffect::DrawWater(int /*page*/, int /*LightModifier*/, DWORD* pSrcImage, DWORD* pTargetImage)
190 int dx, dy;
191 int x, y;
192 DWORD c;
194 int offset = m_iWidth + 1;
195 long lIndex;
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;
216 offset++;
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
246 if(color < 0)
247 return 0;
248 if(color > 255)
249 return 255;
250 return color;