📄 barshader.cpp
字号:
#include "StdAfx.h"
#include "emule.h"
#include "barshader.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
// Barry
#ifndef PI
#define PI 3.14159265358979323846264338328
#endif
#define HALF(X) (((X) + 1) / 2)
CBarShader::CBarShader(uint32 height, uint32 width) {
m_iWidth = width;
m_iHeight = height;
m_uFileSize = 1;
m_FirstSpan = new BarSpan(0, 1);
m_Modifiers = NULL;
}
CBarShader::~CBarShader(void) {
delete[] m_Modifiers;
m_FirstSpan->DeleteUpTo(NULL);
delete m_FirstSpan;
}
void CBarShader::Reset() {
Fill(0);
}
void CBarShader::BuildModifiers() {
if(m_Modifiers != NULL)
delete[] m_Modifiers;
m_used3dlevel=theApp.glob_prefs->Get3DDepth();
// Barry - New property page slider to control depth of gradient
// Depth must be at least 2
// 2 gives greatest depth, the higher the value, the flatter the appearance
// m_Modifiers[count-1] will always be 1, m_Modifiers[0] depends on the value of depth
int depth = (7-theApp.glob_prefs->Get3DDepth());
int count = HALF(m_iHeight);
double piOverDepth = PI/depth;
double base = piOverDepth * ((depth / 2.0) - 1);
double increment = piOverDepth / (count - 1);
m_Modifiers = new float[count];
for (int i = 0; i < count; i++)
m_Modifiers[i] = (float)(sin(base + i * increment));
}
void CBarShader::SetFileSize(uint32 fileSize) {
if(m_uFileSize != fileSize) {
m_uFileSize = fileSize;
m_dPixelsPerByte = (double)m_iWidth / m_uFileSize;
m_dBytesPerPixel = (double)m_uFileSize / m_iWidth;
}
}
void CBarShader::FillRange(uint32 start, uint32 end, COLORREF color) {
if(end > m_uFileSize)
end = m_uFileSize;
if(start >= end)
return;
BarSpan *bsPrev, *bsStart, *bsEnd;
bsPrev = bsStart = m_FirstSpan;
while(bsStart->next != NULL && bsStart->end < start)
bsStart = bsStart->next;
//place new span, unless it's the same color
BarSpan *bsNew;
//case 0, same color
if(bsStart->color == color) {
//same color, ends before end.
if(bsStart->end > end)
return;
//case 1, same color, ends after end.
bsNew = bsStart;
bsNew->end = end;
}
else if(bsStart->start == start) {
//case 2, begins at start, ends before end.
if(bsStart->end > end) {
//the 'ol switcheroo
bsNew = new BarSpan(bsStart, end, bsStart->end, bsStart->color);
bsStart->end = end;
bsStart->color = color;
return;
}
//case 3, begins at start, ends after end.
else {
//hostile takeover
bsNew = bsStart;
bsNew->end = end;
bsNew->color = color;
}
}
else if(bsStart->start < start) {
//case 4, begins after start, ends before end
if(bsStart->end > end) {
bsNew = new BarSpan(bsStart, start, end, color);
bsNew = new BarSpan(bsNew, end, bsStart->end, bsStart->color);
bsStart->end = start;
return;
}
//case 5, begins after start, ends after end
else {
bsNew = new BarSpan(bsStart, start, end, color);
bsStart->end = start;
}
} else {
ASSERT(FALSE);//should never get here
}
bsEnd = bsNew->next;
while(bsEnd != NULL && bsEnd->end <= end)
bsEnd = bsEnd->next;
if(bsEnd != NULL)
bsEnd->start = end;
bsNew->DeleteUpTo(bsEnd);
}
void CBarShader::Fill(COLORREF color) {
m_FirstSpan->DeleteUpTo(NULL);
m_FirstSpan->start = 0;
m_FirstSpan->end = m_uFileSize;
m_FirstSpan->color = color;
}
void CBarShader::Draw(CDC* dc, int iLeft, int iTop, bool bFlat) {
BarSpan *bsCurrent = m_FirstSpan;
RECT rectSpan;
rectSpan.top = iTop;
rectSpan.bottom = iTop + m_iHeight;
rectSpan.right = iLeft;
int iBytesInOnePixel = (int)(m_dBytesPerPixel + 0.5f);
uint32 start = 0;//bsCurrent->start;
while(bsCurrent != NULL && rectSpan.right < (iLeft + m_iWidth)) {
uint32 uSpan = bsCurrent->end - start;
int iPixels = (int)(uSpan * m_dPixelsPerByte + 0.5f);
if(iPixels > 0) {
rectSpan.left = rectSpan.right;
rectSpan.right += iPixels;
FillRect(dc, &rectSpan, bsCurrent->color, bFlat);
start += (int)(iPixels * m_dBytesPerPixel + 0.5f);
} else {
float fRed = 0;
float fGreen = 0;
float fBlue = 0;
uint32 iEnd = start + iBytesInOnePixel;
int iLast = start;
do {
float fWeight = (min(bsCurrent->end, iEnd) - iLast) * m_dPixelsPerByte;
fRed += GetRValue(bsCurrent->color) * fWeight;
fGreen += GetGValue(bsCurrent->color) * fWeight;
fBlue += GetBValue(bsCurrent->color) * fWeight;
if(bsCurrent->end > iEnd)
break;
iLast = bsCurrent->end;
bsCurrent = bsCurrent->next;
} while(bsCurrent != NULL);
rectSpan.left = rectSpan.right;
rectSpan.right++;
FillRect(dc, &rectSpan, fRed, fGreen, fBlue, bFlat);
start += iBytesInOnePixel;
}
while(bsCurrent != NULL && bsCurrent->end < start)
bsCurrent = bsCurrent->next;
}
}
void CBarShader::FillRect(CDC *dc, LPRECT rectSpan, COLORREF color, bool bFlat) {
if(!color || bFlat)
dc->FillRect(rectSpan, &CBrush(color));
else
FillRect(dc, rectSpan, GetRValue(color), GetGValue(color), GetBValue(color), false);
}
void CBarShader::FillRect(CDC *dc, LPRECT rectSpan, float fRed, float fGreen,
float fBlue, bool bFlat) {
if(bFlat) {
COLORREF color = RGB((int)(fRed + .5f), (int)(fGreen + .5f), (int)(fBlue + .5f));
dc->FillRect(rectSpan, &CBrush(color));
} else {
if (m_Modifiers == NULL || m_used3dlevel!=theApp.glob_prefs->Get3DDepth())
BuildModifiers();
RECT rect;
memcpy(&rect, rectSpan, sizeof(RECT));
int iTop = rect.top;
int iBot = rect.bottom;
int iMax = HALF(m_iHeight);
for(int i = 0; i < iMax; i++) {
CBrush cbNew(RGB((int)(fRed * m_Modifiers[i] + .5f), (int)(fGreen * m_Modifiers[i] + .5f), (int)(fBlue * m_Modifiers[i] + .5f)));
rect.top = iTop + i;
rect.bottom = iTop + i + 1;
dc->FillRect(&rect, &cbNew);
rect.top = iBot - i - 1;
rect.bottom = iBot - i;
dc->FillRect(&rect, &cbNew);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -