Upstream tarball 20080522
[amule.git] / src / BarShader.cpp
blobe22df52b14bc01a7870bdc19e1e4d5f56f14eb46
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 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 "Color.h" // Needed for RGB
29 #include "BarShader.h" // Interface declarations.
31 const double Pi = 3.14159265358979323846264338328;
33 #define HALF(X) (((X) + 1) / 2)
34 #define DEFAULT_DEPTH 10
37 CBarShader::CBarShader(uint32 height, uint32 width)
38 : m_Width( width ),
39 m_Height( height ),
40 m_FileSize( 1 ),
41 m_Modifiers( NULL ),
42 m_used3dlevel( DEFAULT_DEPTH ),
43 m_Content(width, 0)
48 CBarShader::~CBarShader()
50 if ( m_Modifiers ) {
51 delete[] m_Modifiers;
56 void CBarShader::SetFileSize(uint64 fileSize)
58 m_FileSize = fileSize;
62 void CBarShader::SetHeight( int height )
64 if( m_Height != height ) {
65 m_Height = height;
67 // Reset the modifers
68 if ( m_Modifiers ) {
69 delete[] m_Modifiers;
70 m_Modifiers = NULL;
76 void CBarShader::SetWidth(int width)
78 m_Width = width;
79 m_Content.clear();
80 m_Content.resize(m_Width, 0);
84 void CBarShader::Set3dDepth( int depth )
86 if ( depth < 1 ) {
87 depth = 1;
88 } else if ( depth > 5 ) {
89 depth = 5;
92 if ( m_used3dlevel != depth ) {
93 m_used3dlevel = depth;
95 // Reset the modifers
96 if ( m_Modifiers ) {
97 delete[] m_Modifiers;
98 m_Modifiers = NULL;
104 void CBarShader::BuildModifiers()
106 if ( m_Modifiers ) {
107 delete[] m_Modifiers;
110 int depth = (7-m_used3dlevel);
111 int 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 (int i = 0; i < count; i++)
118 m_Modifiers[i] = (double)(sin(base + i * increment));
122 void CBarShader::FillRange(uint64 start, uint64 end, uint32 color)
124 if (start >= end || start >= m_FileSize) {
125 return;
128 // precision for small files: end must be increased by one
129 // think of each byte as a visible block, then start points to
130 // the beginning of its block, but end points to the END of its block
131 end++;
133 if (end > m_FileSize) {
134 end = m_FileSize;
137 uint32 firstPixel = start * m_Width / m_FileSize;
138 uint32 lastPixel = end * m_Width / m_FileSize;
139 if (lastPixel == m_Width) {
140 lastPixel--;
142 double f_Width = m_Width;
143 // calculate how much of this pixels is to be covered with the fill
144 double firstCovered = firstPixel + 1 - start * f_Width / m_FileSize;
145 double lastCovered = end * f_Width / m_FileSize - lastPixel;
146 // all inside one pixel ?
147 if (firstPixel == lastPixel) {
148 BlendPixel(firstPixel, color, firstCovered + lastCovered - 1.0);
149 } else {
150 BlendPixel(firstPixel, color, firstCovered);
151 BlendPixel(lastPixel, color, lastCovered);
152 // fill pixels between (if any)
153 for (uint32 i = firstPixel + 1; i < lastPixel; i++) {
154 m_Content[i] = color;
160 // This function is responsible for drawing ranges that are too small
161 // to fill a single pixel. To overcome this problem, we gather the
162 // sum of ranges until we have enough to draw a single pixel. The
163 // color of this pixel will be the sum of the colors of the ranges
164 // within the single pixel, each weighted after its relative size.
165 void CBarShader::BlendPixel(uint32 index, uint32 color, double covered)
167 uint32 oldcolor = m_Content[index];
168 // Colors are added up, so the bar must be initialized black (zero) for blending to work.
169 // So after blending in 10 * the same color with covered == 0.1, the pixel will
170 // have the color.
171 // Blending in black will thus have no effect.
172 // This works as long each part of the virtual bar is overwritten just once (or left black).
173 int Red = (int) (GetRValue(oldcolor) + GetRValue(color) * covered + 0.5);
174 int Green = (int) (GetGValue(oldcolor) + GetGValue(color) * covered + 0.5);
175 int Blue = (int) (GetBValue(oldcolor) + GetBValue(color) * covered + 0.5);
176 Red = Red > 255 ? 255 : Red ;
177 Green = Green > 255 ? 255 : Green;
178 Blue = Blue > 255 ? 255 : Blue ;
179 m_Content[index] = RGB(Red, Green, Blue);
183 void CBarShader::Fill(uint32 color)
185 m_Content.clear();
186 m_Content.resize(m_Width, color);
190 void CBarShader::Draw( wxDC* dc, int iLeft, int iTop, bool bFlat )
192 wxASSERT( dc );
194 // Do we need to rebuild the modifiers?
195 if ( !bFlat && !m_Modifiers ) {
196 BuildModifiers();
199 wxRect rectSpan;
200 rectSpan.x = iLeft;
201 rectSpan.y = iTop;
202 rectSpan.height = m_Height;
203 rectSpan.width = 0;
204 uint32 lastcolor = 0xffffffff; // invalid value
206 dc->SetPen(*wxTRANSPARENT_PEN);
208 // draw each pixel, draw same colored pixels together
209 for (int x = 0; x < m_Width; x++) {
210 uint32 color = m_Content[x];
211 if (color == lastcolor) {
212 rectSpan.width++;
213 } else {
214 if (rectSpan.width) {
215 FillRect(dc, rectSpan, lastcolor, bFlat);
216 rectSpan.x += rectSpan.width;
218 rectSpan.width = 1;
219 lastcolor = color;
222 FillRect(dc, rectSpan, lastcolor, bFlat);
226 void CBarShader::FillRect(wxDC *dc, const wxRect& rectSpan, uint32 color, bool bFlat)
228 wxASSERT( dc );
230 if( bFlat || !color ) {
231 wxBrush brush( WxColourFromCr(color), wxSOLID );
232 dc->SetBrush( brush );
233 dc->DrawRectangle( rectSpan );
234 } else {
235 int x1 = rectSpan.x;
236 int x2 = rectSpan.x + rectSpan.width;
237 int y1 = rectSpan.y;
238 int y2 = rectSpan.GetBottom();
240 int Max = HALF(m_Height);
241 for (int i = 0; i < Max; i++) {
242 int cRed = std::min( 255, (int)(GetRValue(color) * m_Modifiers[i] + .5f) );
243 int cGreen = std::min( 255, (int)(GetGValue(color) * m_Modifiers[i] + .5f) );
244 int cBlue = std::min( 255, (int)(GetBValue(color) * m_Modifiers[i] + .5f) );
246 wxPen pen( wxColour( cRed, cGreen, cBlue ), 1, wxSOLID );
247 dc->SetPen( pen );
249 // Draw top row
250 dc->DrawLine( x1, y1 + i, x2, y1 + i );
252 // Draw bottom row
253 dc->DrawLine( x1, y2 - i, x2, y2 - i );
257 dc->SetBrush(wxNullBrush);
259 // File_checked_for_headers