Upstream tarball 9861
[amule.git] / src / BarShader.cpp
blob95ad6be966f1bcdf53182890efa249c0e50d20a9
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 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.
20 //
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 const double Pi = 3.14159265358979323846264338328;
33 #define HALF(X) (((X) + 1) / 2)
34 #define DEFAULT_DEPTH 10
36 CBarShader::CBarShader(unsigned height, unsigned width)
37 : m_Width( width ),
38 m_Height( height ),
39 m_FileSize( 1 ),
40 m_Modifiers( NULL ),
41 m_used3dlevel( DEFAULT_DEPTH ),
42 m_Content(width, 0)
47 CBarShader::~CBarShader()
49 if ( m_Modifiers ) {
50 delete[] m_Modifiers;
55 void CBarShader::SetHeight(unsigned height)
57 if( m_Height != height ) {
58 m_Height = height;
60 // Reset the modifers
61 if ( m_Modifiers ) {
62 delete[] m_Modifiers;
63 m_Modifiers = NULL;
69 void CBarShader::SetWidth(int width)
71 if (width > 0) {
72 m_Width = width;
73 Fill(CMuleColour(0,0,0));
78 void CBarShader::Set3dDepth(unsigned depth)
80 if ( depth < 1 ) {
81 depth = 1;
82 } else if ( depth > 5 ) {
83 depth = 5;
86 if ( m_used3dlevel != depth ) {
87 m_used3dlevel = depth;
89 // Reset the modifers
90 if ( m_Modifiers ) {
91 delete[] m_Modifiers;
92 m_Modifiers = NULL;
98 void CBarShader::BuildModifiers()
100 wxASSERT(m_used3dlevel < 7);
102 if ( m_Modifiers ) {
103 delete[] m_Modifiers;
106 unsigned depth = (7 - m_used3dlevel);
107 unsigned count = HALF(m_Height);
108 double piOverDepth = Pi/depth;
109 double base = piOverDepth * ((depth / 2.0) - 1);
110 double increment = piOverDepth / (count - 1);
112 m_Modifiers = new double[count];
113 for (unsigned i = 0; i < count; i++)
114 m_Modifiers[i] = (double)(sin(base + i * increment));
118 void CBarShader::FillRange(uint64 start, uint64 end, const CMuleColour& colour)
120 wxASSERT(m_FileSize > 0);
122 if (start >= end || start >= m_FileSize) {
123 return;
126 // precision for small files: end must be increased by one
127 // think of each byte as a visible block, then start points to
128 // the beginning of its block, but end points to the END of its block
129 end++;
131 if (end > m_FileSize) {
132 end = m_FileSize;
135 unsigned firstPixel = start * m_Width / m_FileSize;
136 unsigned lastPixel = end * m_Width / m_FileSize;
137 if (lastPixel == m_Width) {
138 lastPixel--;
141 double f_Width = m_Width;
142 // calculate how much of this pixels is to be covered with the fill
143 double firstCovered = firstPixel + 1 - start * f_Width / m_FileSize;
144 double lastCovered = end * f_Width / m_FileSize - lastPixel;
145 // all inside one pixel ?
146 if (firstPixel == lastPixel) {
147 m_Content[firstPixel].BlendWith(colour, firstCovered + lastCovered - 1.0);
148 } else {
149 m_Content[firstPixel].BlendWith(colour, firstCovered);
150 m_Content[lastPixel].BlendWith(colour, lastCovered);
151 // fill pixels between (if any)
152 for (unsigned i = firstPixel + 1; i < lastPixel; i++) {
153 m_Content[i] = colour;
159 void CBarShader::Draw( wxDC* dc, int iLeft, int iTop, bool bFlat )
161 wxASSERT( dc );
163 // Do we need to rebuild the modifiers?
164 if ( !bFlat && !m_Modifiers ) {
165 BuildModifiers();
168 // Render the bar into a raw buffer
169 unsigned char * buf = (unsigned char *) malloc(m_Width * m_Height * 3);
171 if (bFlat) {
172 // draw flat bar
173 unsigned idx = 0;
174 for (unsigned x = 0; x < m_Width; x++) {
175 unsigned cRed = m_Content[x].Red();
176 unsigned cGreen = m_Content[x].Green();
177 unsigned cBlue = m_Content[x].Blue();
178 buf[idx++] = cRed;
179 buf[idx++] = cGreen;
180 buf[idx++] = cBlue;
182 unsigned linelength = idx;
183 unsigned y = 1;
184 for (; y < m_Height >> 1; y <<= 1, idx <<= 1) {
185 std::memcpy(buf + idx, buf, idx);
187 if (y < m_Height) {
188 std::memcpy(buf + idx, buf, (m_Height - y) * linelength);
190 } else {
191 // draw rounded bar
192 unsigned Max = HALF(m_Height);
193 unsigned idx = 0;
194 for (unsigned y = 0; y < Max; y++) {
195 for (unsigned x = 0; x < m_Width; x++) {
196 unsigned cRed = (unsigned)(m_Content[x].Red() * m_Modifiers[y] + .5f);
197 unsigned cGreen = (unsigned)(m_Content[x].Green() * m_Modifiers[y] + .5f);
198 unsigned cBlue = (unsigned)(m_Content[x].Blue() * m_Modifiers[y] + .5f);
199 cRed = std::min(255u, cRed);
200 cGreen = std::min(255u, cGreen);
201 cBlue = std::min(255u, cBlue);
202 buf[idx++] = cRed;
203 buf[idx++] = cGreen;
204 buf[idx++] = cBlue;
207 unsigned linelength = m_Width * 3;
208 for (unsigned y = std::max(Max, m_Height - Max); y < m_Height; y++) {
209 std::memcpy(buf + y * linelength, buf + (m_Height - 1 - y) * linelength, linelength);
212 wxImage image(m_Width, m_Height);
213 image.SetData(buf);
214 wxBitmap bitmap(image);
215 dc->DrawBitmap(bitmap, iLeft, iTop);
217 // File_checked_for_headers