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::SetFileSize(uint64 fileSize
)
58 m_FileSize
= fileSize
;
62 void CBarShader::SetHeight( int height
)
64 if( m_Height
!= height
) {
76 void CBarShader::SetWidth(int width
)
80 m_Content
.resize(m_Width
, 0);
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
, uint32 color
)
124 if (start
>= end
|| start
>= m_FileSize
) {
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
133 if (end
> m_FileSize
) {
137 uint32 firstPixel
= start
* m_Width
/ m_FileSize
;
138 uint32 lastPixel
= end
* m_Width
/ m_FileSize
;
139 if (lastPixel
== m_Width
) {
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);
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
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
)
186 m_Content
.resize(m_Width
, color
);
190 void CBarShader::Draw( wxDC
* dc
, int iLeft
, int iTop
, bool bFlat
)
194 // Do we need to rebuild the modifiers?
195 if ( !bFlat
&& !m_Modifiers
) {
202 rectSpan
.height
= m_Height
;
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
) {
214 if (rectSpan
.width
) {
215 FillRect(dc
, rectSpan
, lastcolor
, bFlat
);
216 rectSpan
.x
+= rectSpan
.width
;
222 FillRect(dc
, rectSpan
, lastcolor
, bFlat
);
226 void CBarShader::FillRect(wxDC
*dc
, const wxRect
& rectSpan
, uint32 color
, bool bFlat
)
230 if( bFlat
|| !color
) {
231 wxBrush
brush( WxColourFromCr(color
), wxSOLID
);
232 dc
->SetBrush( brush
);
233 dc
->DrawRectangle( rectSpan
);
236 int x2
= rectSpan
.x
+ rectSpan
.width
;
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
);
250 dc
->DrawLine( x1
, y1
+ i
, x2
, y1
+ i
);
253 dc
->DrawLine( x1
, y2
- i
, x2
, y2
- i
);
257 dc
->SetBrush(wxNullBrush
);
259 // File_checked_for_headers