2 // This file is part of the aMule Project.
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 )
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
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
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
)
42 m_used3dlevel( DEFAULT_DEPTH
)
48 CBarShader::~CBarShader()
56 void CBarShader::Reset()
63 void CBarShader::SetFileSize(uint64 fileSize
)
65 m_FileSize
= fileSize
;
70 void CBarShader::SetHeight( int height
)
72 if( m_Height
!= height
) {
84 void CBarShader::Set3dDepth( int depth
)
88 } else if ( depth
> 5 ) {
92 if ( m_used3dlevel
!= depth
) {
93 m_used3dlevel
= depth
;
104 void CBarShader::BuildModifiers()
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
, const uint32 color
)
125 wxASSERT( start
<= end
);
127 if ( start
>= m_FileSize
) {
131 if ( end
>= m_FileSize
) {
132 end
= m_FileSize
- 1;
135 m_spanlist
.insert( start
, end
, color
);
139 void CBarShader::Fill(uint32 color
)
142 m_spanlist
.insert( 0, m_FileSize
- 1, color
);
146 void CBarShader::Draw( wxDC
* dc
, int iLeft
, int iTop
, bool bFlat
)
150 // Check if there's anything to do ...
151 if ( m_spanlist
.empty() ) {
156 // Do we need to rebuild the modifiers?
157 if ( !bFlat
&& !m_Modifiers
) {
164 rectSpan
.height
= m_Height
;
167 dc
->SetPen(*wxTRANSPARENT_PEN
);
169 // This modifier is multipled with sizes to allow for better handling of small ranges
170 const uint64 MOD
= 1000;
171 // This is the number of bits each pixel should contain.
172 const uint64 bitsPerPixel
= (m_FileSize
* MOD
) / (uint64
)m_Width
;
174 // The initial values for partial pixel drawing
180 // Initialize to the first range
181 SpanList::iterator it
= m_spanlist
.begin();
182 uint64 size
= (uint64
)( it
.keyEnd() - it
.keyStart() + 1 ) * MOD
;
183 uint32 color
= *it
++;
185 // Loop until everything has been drawn
186 while ( size
|| curPixel
) {
187 if ( !size
&& it
!= m_spanlist
.end() ) {
188 // Fetch the next range and increment the iterator
189 size
= (uint64
)( it
.keyEnd() - it
.keyStart() + 1 ) * MOD
;
191 } else if ( curPixel
|| size
< bitsPerPixel
) {
192 // This block is responsible for drawing ranges that are too small
193 // to fill a single pixel. To overcome this problem, we gather the
194 // sum of ranges until we have enough to draw a single pixel. The
195 // color of this pixel will be the sum of the colors of the ranges
196 // within the single pixel, each weighted after its relative size.
198 // See how much we can take from the current range
199 uint64 curDiff
= std::min( size
, bitsPerPixel
- curPixel
);
201 // Increment the current size of the partial pixel
204 // Add the color of the current range times the ammount of the current
205 // range that was added to the partial pixel. The result will be divided
206 // by the length of the partial pixel to get the average.
207 curRed
+= curDiff
* GetRValue( color
);
208 curGreen
+= curDiff
* GetGValue( color
);
209 curBlue
+= curDiff
* GetBValue( color
);
211 // If we have a complete pixel, or if we have run out of usable ranges,
212 // then draw the partial pixel. Note that size is modified below this
213 // check, so that it only triggers when size was 0 to begin with.
214 if ( curPixel
== bitsPerPixel
|| !size
) {
215 // Draw a single line containing the average of the smaller parts
216 uint32 col
= RGB( (uint32
)(curRed
/ curPixel
),
217 (uint32
)(curGreen
/ curPixel
),
218 (uint32
)(curBlue
/ curPixel
) );
220 // Reset the partial-pixel
221 curPixel
= curRed
= curGreen
= curBlue
= 0;
223 // Increment the position on the device-context
224 rectSpan
.x
+= rectSpan
.width
;
228 FillRect(dc
, rectSpan
, col
, bFlat
);
234 // We are dealing with a range that is large enough to draw by itself.
235 // We will draw as many complete pixels as we can, and allow the rest
236 // to be absorbed by the partial pixel.
237 rectSpan
.x
+= rectSpan
.width
;
238 rectSpan
.width
= size
/ bitsPerPixel
;
240 // Unused size will be used by the partial-pixel drawing code.
241 size
= size
% bitsPerPixel
;
244 FillRect(dc
, rectSpan
, color
, bFlat
);
250 void CBarShader::FillRect(wxDC
*dc
, const wxRect
& rectSpan
, uint32 color
, bool bFlat
)
254 if( bFlat
|| !color
) {
255 wxBrush
brush( WxColourFromCr(color
), wxSOLID
);
256 dc
->SetBrush( brush
);
257 dc
->DrawRectangle( rectSpan
);
260 int x2
= rectSpan
.x
+ rectSpan
.width
;
262 int y2
= rectSpan
.GetBottom();
264 int Max
= HALF(m_Height
);
265 for (int i
= 0; i
< Max
; i
++) {
266 int cRed
= std::min( 255, (int)(GetRValue(color
) * m_Modifiers
[i
] + .5f
) );
267 int cGreen
= std::min( 255, (int)(GetGValue(color
) * m_Modifiers
[i
] + .5f
) );
268 int cBlue
= std::min( 255, (int)(GetBValue(color
) * m_Modifiers
[i
] + .5f
) );
270 wxPen
pen( wxColour( cRed
, cGreen
, cBlue
), 1, wxSOLID
);
274 dc
->DrawLine( x1
, y1
+ i
, x2
, y1
+ i
);
277 dc
->DrawLine( x1
, y2
- i
, x2
, y2
- i
);
281 dc
->SetBrush(wxNullBrush
);
283 // File_checked_for_headers