Updated changelog
[amule.git] / src / BarShader.cpp
blobc6f8889c0f13bf816e26a62af6c558959b1e0b2a
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <wx/dc.h>
27 #include <wx/image.h>
28 #include "BarShader.h" // Interface declarations.
29 #include <cstring> // Needed for std::memcpy
31 #if defined(_MSC_VER) && (_MSC_VER >= 1800)
32 #include <algorithm> // for std::min and std::max
33 #endif
35 const double Pi = 3.14159265358979323846264338328;
37 #define HALF(X) (((X) + 1) / 2)
38 #define DEFAULT_DEPTH 10
40 CBarShader::CBarShader(unsigned height, unsigned width)
41 : m_Width( width ),
42 m_Height( height ),
43 m_FileSize( 1 ),
44 m_Modifiers( NULL ),
45 m_used3dlevel( DEFAULT_DEPTH ),
46 m_Content(width, 0)
51 CBarShader::~CBarShader()
53 if ( m_Modifiers ) {
54 delete[] m_Modifiers;
59 void CBarShader::SetHeight(unsigned height)
61 if( m_Height != height ) {
62 m_Height = height;
64 // Reset the modifers
65 if ( m_Modifiers ) {
66 delete[] m_Modifiers;
67 m_Modifiers = NULL;
73 void CBarShader::SetWidth(int width)
75 if (width > 0) {
76 m_Width = width;
77 Fill(CMuleColour(0,0,0));
82 void CBarShader::Set3dDepth(unsigned depth)
84 if ( depth < 1 ) {
85 depth = 1;
86 } else if ( depth > 5 ) {
87 depth = 5;
90 if ( m_used3dlevel != depth ) {
91 m_used3dlevel = depth;
93 // Reset the modifers
94 if ( m_Modifiers ) {
95 delete[] m_Modifiers;
96 m_Modifiers = NULL;
102 void CBarShader::BuildModifiers()
104 wxASSERT(m_used3dlevel < 7);
106 if ( m_Modifiers ) {
107 delete[] m_Modifiers;
110 unsigned depth = (7 - m_used3dlevel);
111 unsigned count = HALF(m_Height);
112 double piOverDepth = Pi/depth;
113 double base = piOverDepth * ((depth / 2.0) - 1);
114 double increment = piOverDepth / (count - 1);
116 m_Modifiers = new double[count];
117 for (unsigned i = 0; i < count; i++)
118 m_Modifiers[i] = (double)(sin(base + i * increment));
122 void CBarShader::FillRange(uint64 start, uint64 end, const CMuleColour& colour)
124 wxASSERT(m_FileSize > 0);
126 if (start >= end || start >= m_FileSize) {
127 return;
130 // precision for small files: end must be increased by one
131 // think of each byte as a visible block, then start points to
132 // the beginning of its block, but end points to the END of its block
133 end++;
135 if (end > m_FileSize) {
136 end = m_FileSize;
139 unsigned firstPixel = start * m_Width / m_FileSize;
140 unsigned lastPixel = end * m_Width / m_FileSize;
141 if (lastPixel == m_Width) {
142 lastPixel--;
145 double f_Width = m_Width;
146 // calculate how much of this pixels is to be covered with the fill
147 double firstCovered = firstPixel + 1 - start * f_Width / m_FileSize;
148 double lastCovered = end * f_Width / m_FileSize - lastPixel;
149 // all inside one pixel ?
150 if (firstPixel == lastPixel) {
151 m_Content[firstPixel].BlendWith(colour, firstCovered + lastCovered - 1.0);
152 } else {
153 m_Content[firstPixel].BlendWith(colour, firstCovered);
154 m_Content[lastPixel].BlendWith(colour, lastCovered);
155 // fill pixels between (if any)
156 for (unsigned i = firstPixel + 1; i < lastPixel; i++) {
157 m_Content[i] = colour;
163 void CBarShader::Draw( wxDC* dc, int iLeft, int iTop, bool bFlat )
165 wxASSERT( dc );
167 // Do we need to rebuild the modifiers?
168 if ( !bFlat && !m_Modifiers ) {
169 BuildModifiers();
172 // Render the bar into a raw buffer
173 unsigned char * buf = (unsigned char *) malloc(m_Width * m_Height * 3);
175 if (bFlat) {
176 // draw flat bar
177 unsigned idx = 0;
178 for (unsigned x = 0; x < m_Width; x++) {
179 unsigned cRed = m_Content[x].Red();
180 unsigned cGreen = m_Content[x].Green();
181 unsigned cBlue = m_Content[x].Blue();
182 buf[idx++] = cRed;
183 buf[idx++] = cGreen;
184 buf[idx++] = cBlue;
186 unsigned linelength = idx;
187 unsigned y = 1;
188 for (; y < m_Height >> 1; y <<= 1, idx <<= 1) {
189 std::memcpy(buf + idx, buf, idx);
191 if (y < m_Height) {
192 std::memcpy(buf + idx, buf, (m_Height - y) * linelength);
194 } else {
195 // draw rounded bar
196 unsigned Max = HALF(m_Height);
197 unsigned idx = 0;
198 for (unsigned y = 0; y < Max; y++) {
199 for (unsigned x = 0; x < m_Width; x++) {
200 unsigned cRed = (unsigned)(m_Content[x].Red() * m_Modifiers[y] + .5f);
201 unsigned cGreen = (unsigned)(m_Content[x].Green() * m_Modifiers[y] + .5f);
202 unsigned cBlue = (unsigned)(m_Content[x].Blue() * m_Modifiers[y] + .5f);
203 cRed = std::min(255u, cRed);
204 cGreen = std::min(255u, cGreen);
205 cBlue = std::min(255u, cBlue);
206 buf[idx++] = cRed;
207 buf[idx++] = cGreen;
208 buf[idx++] = cBlue;
211 unsigned linelength = m_Width * 3;
212 for (unsigned y = std::max(Max, m_Height - Max); y < m_Height; y++) {
213 std::memcpy(buf + y * linelength, buf + (m_Height - 1 - y) * linelength, linelength);
216 wxImage image(m_Width, m_Height);
217 image.SetData(buf);
218 wxBitmap bitmap(image);
219 dc->DrawBitmap(bitmap, iLeft, iTop);
221 // File_checked_for_headers