void GetRGB(LONG cr, byte& R, byte& G, byte& B)
{
byte *pTemp = (byte *)&cr;
R = *pTemp;
G = *(pTemp+1);
B = *(pTemp+2);
};
void GetTightXYBox(XYZ* i_ptArray, long i_nPtsNum, XYZ* io_ptMin, XYZ* io_ptMax)
{
io_ptMin->x = 1e10;
io_ptMin->y = 1e10;
io_ptMax->x = 0;
io_ptMax->y = 0;
for (int i = 0; i < i_nPtsNum; i++)
{
int iX = i_ptArray[i].x;
int iY = i_ptArray[i].y;
if (iX > io_ptMax->x)
{
io_ptMax->x = iX;
}
if (iX < io_ptMin->x)
{
io_ptMin->x = iX;
}
if (iY > io_ptMax->y)
{
io_ptMax->y = iY;
}
if (iY < io_ptMin->y)
{
io_ptMin->y = iY;
}
}
}
GraphicsPath* GetRectanglePath(POINT* i_ptArray, long i_nPtsNum, double i_dGrdAngle, PointF* io_pCenterPt, PointF* io_pt1, PointF* io_pt2)
{
// 获取点的包围盒
GraphicsPath* path = new GraphicsPath;
CMatrix mat1, mat2;
XYZ* ptArraty = new XYZ[i_nPtsNum];
for (int i = 0; i < i_nPtsNum; i++)
{
ptArraty[i].x = i_ptArray[i].x;
ptArraty[i].y = i_ptArray[i].y;
ptArraty[i].z = 0;
}
XYZ ptLB, ptRT;
GetTightXYBox(ptArraty, i_nPtsNum, &ptLB, &ptRT);
delete[] ptArraty;
XYZ ptCenter((ptLB.x + ptRT.x)*0.5, (ptLB.y + ptRT.y)*0.5, 0);
mat1.GetRotMat(ptCenter, 0, 0, i_dGrdAngle);
mat2.GetRotMat(ptCenter, 0, 0, -i_dGrdAngle);
// 点的包围盒旋转 -i_dGrdAngle
long ptNumBox = 4;
XYZ ptBox1[] = { XYZ(ptLB.x, ptRT.y, 0), XYZ(ptRT.x, ptRT.y, 0),
XYZ(ptRT.x, ptLB.y, 0), XYZ(ptLB.x, ptLB.y, 0) };
for (int i = 0; i < ptNumBox; i++)
{
ptBox1[i].Trans(mat1);
}
// 获得新的包围盒
GetTightXYBox(ptBox1, ptNumBox, &ptLB, &ptRT);
XYZ ptBox2[] = { XYZ(ptLB.x, ptRT.y, 0), XYZ(ptRT.x, ptRT.y, 0),
XYZ(ptRT.x, ptLB.y, 0), XYZ(ptLB.x, ptLB.y, 0) };
// 获得新的包围盒 i_dGrdAngle
PointF ptFBox[4];
for (int i = 0; i < ptNumBox; i++)
{
ptBox2[i].Trans(mat2);
ptFBox[i].X = ptBox2[i].x;
ptFBox[i].Y = ptBox2[i].y;
if (fabs(ptFBox[i].X) < 1e-8)
ptFBox[i].X = 0.0f;
if (fabs(ptFBox[i].Y) < 1e-8)
ptFBox[i].Y = 0.0f;
}
// 返回路径和中心点
path->AddLines(ptFBox, ptNumBox);
io_pCenterPt->X = ptCenter.x;
io_pCenterPt->Y = ptCenter.y;
io_pt1->X = ptFBox[3].X;
io_pt1->Y = ptFBox[3].Y;
io_pt2->X = ptFBox[2].X;
io_pt2->Y = ptFBox[2].Y;
return path;
}
enum pathType
{
HemiSpherical = 0,
Spherical = 1,
Curved = 2
};
GraphicsPath* GetEllipsePath(POINT* i_ptArray, long i_nPtsNum, double i_dGrdAngle, PointF* io_pCenterPt, pathType type, bool i_isInCenter)
{
GraphicsPath* path = new GraphicsPath;
CMatrix mat1, mat2, mat3;
bool isInCenter = i_isInCenter;
float angle = i_dGrdAngle;
XYZ* ptArraty = new XYZ[i_nPtsNum];
for (int i = 0; i < i_nPtsNum; i++)
{
ptArraty[i].x = i_ptArray[i].x;
ptArraty[i].y = i_ptArray[i].y;
ptArraty[i].z = 0;
}
XYZ ptLB, ptRT;
GetTightXYBox(ptArraty, i_nPtsNum, &ptLB, &ptRT);
delete[] ptArraty;
XYZ ptCenter((ptLB.x + ptRT.x)*0.5, (ptLB.y + ptRT.y)*0.5, 0);
mat1.GetRotMat(ptCenter, 0, 0, angle);
mat2.GetRotMat(ptCenter, 0, 0, -angle);
mat3.GetRotMat(ptCenter, 0, 0, -(i_dGrdAngle + (float)PI / 4.0));
double dx = fabs(ptLB.x - ptRT.x);
double dy = fabs(ptLB.y - ptRT.y);
INT radia = sqrt(2.0 * max(dx, dy) * max(dx, dy));
if (type == Spherical)
{
if (!isInCenter)
{
ptCenter.y = ptCenter.y - (float)radia / 4.0;
ptCenter.Trans(mat3);
}
path->AddEllipse((INT)ptCenter.x - radia, (INT)ptCenter.y - radia, (INT)radia*2.0, (INT)radia*2.0);
io_pCenterPt->X = ptCenter.x;
io_pCenterPt->Y = ptCenter.y;
return path;
}
// 点的包围盒旋转 -i_dGrdAngle
long ptNumBox = 4;
XYZ ptBox1[] = { XYZ(ptLB.x, ptRT.y, 0), XYZ(ptRT.x, ptRT.y, 0),
XYZ(ptRT.x, ptLB.y, 0), XYZ(ptLB.x, ptLB.y, 0) };
for (int i = 0; i < ptNumBox; i++)
{
ptBox1[i].Trans(mat1);
}
// 重新获取包围盒
GetTightXYBox(ptBox1, ptNumBox, &ptLB, &ptRT);
dx = fabs(ptLB.x - ptRT.x);
dy = fabs(ptLB.y - ptRT.y);
if (type == HemiSpherical)
{
radia = 2 * max(dx, dy);
if (!isInCenter)
{
ptCenter.x -= (float)radia / 4.0;
}
ptCenter.y += (float)radia / 4.0;
ptCenter.Trans(mat2);
path->AddEllipse((INT)ptCenter.x - radia, (INT)ptCenter.y - radia, (INT)radia*2.0, (INT)radia*2.0);
}
if (type == Curved)
{
ptCenter.x = (ptLB.x + ptRT.x) * 0.5;
ptCenter.y += dy / 2;
path->AddEllipse((INT)(-dx * 1.5), (INT)(-dy), (INT)dx * 3.0, (INT)dy * 2.0);
if (!isInCenter)
{
ptCenter.x -= dx / 2.0;
}
ptCenter.Trans(mat2);
// 旋转椭圆
Matrix m(cos(-angle), sin(-angle), -sin(-angle), cos(-angle), ptCenter.x, (INT)ptCenter.y);
path->Transform(&m);
}
io_pCenterPt->X = ptCenter.x;
io_pCenterPt->Y = ptCenter.y;
return path;
}
bool CCxGiDeviceBM::FillPPInGrdClr(long i_nPtsNum, INT* i_lpPolyCounts, long i_nPolygonCount, HDC i_hDC)
{
if(VARIANT_FALSE == m_vbPenGrdClr)
{
return false;
}
BYTE alpha = 255; // 透明度
// 待填充路径
GraphicsPath graphticPath;
int t(0);
for (long i = 0; i < i_nPolygonCount; i++)
{
int lPtsCount = i_lpPolyCounts[i];
Point* pts = new Point[lPtsCount];
for (int j = 0; j < lPtsCount; j++)
{
pts[j].X = m_ptArray[t].x;
pts[j].Y = m_ptArray[t].y;
t++;
}
graphticPath.SetFillMode(FillModeWinding);
graphticPath.AddLines(pts, lPtsCount);
delete[] pts;
}
// 填充类型 颜色种类
CString sShape = (COLE2T)(m_bsGrdClrShape);
byte r1, b1, g1;
GetRGB(m_crDraw, r1, g1, b1);
byte r2, b2, g2;
GetRGB(m_crGrdColor2, r2, g2, b2);
Color color1(alpha, r1, g1, b1);
Color color2(alpha, r2, g2, b2);
Color colorCenter(alpha, (r1 + r2) / 2, (g1 + g2) / 2, (b1 + b2) / 2);
if (-1 != sShape.Find(_T("INV")))
{
Color tempCol = color1;
color1 = color2;
color2 = tempCol;
}
Graphics graphics(i_hDC);
// 直线型,圆柱形,反转圆柱形
if (_T("LINEAR") == sShape || _T("CYLINDER") == sShape || _T("INVCYLINDER") == sShape)
{
// 线性渐变画刷
PointF ptCenter, pt1, pt2;
GraphicsPath* path = GetRectanglePath(m_ptArray, i_nPtsNum, m_dGrdAngle, &ptCenter, &pt1, &pt2);
LinearGradientBrush* linGrBrush = new LinearGradientBrush(pt1, pt2, color1, color2);
// 等分成 12 等份
int numDiv = 13;
float* intensities = new float[numDiv + 1];
float* positions = new float[numDiv + 1];
float angleDiv = (float)PI / numDiv;
float posDiv1 = 1.0 / numDiv;
float posDiv2 = 1.0 / numDiv;
int numPart = numDiv / 2.0;
float posPart = posDiv1 * numPart;
// 非居中
if (m_vbGCenInCen == VARIANT_FALSE)
{
posDiv1 = 0.25 / numPart;
posDiv2 = 0.75 / (numDiv - numPart);
posPart = posDiv1 * numPart;
}
for (int i = 0; i < numDiv + 1; i++)
{
if (_T("LINEAR") != sShape)
intensities[i] = sin(angleDiv * i);
else
intensities[i] = (float)i / numDiv;
if (i <= numPart)
positions[i] = (float)i * posDiv1;
else
positions[i] = (float)(i - numPart) * posDiv2 + posPart;
}
linGrBrush->SetBlend(intensities, positions, numDiv + 1);
delete[] intensities;
delete[] positions;
// 填充
//graphics.FillRectangle(linGrBrush, 0, 30, 1600, 10);
graphics.FillPath(linGrBrush, &graphticPath);
delete path;
delete linGrBrush;
return true;
}
if (_T("SPHERICAL") == sShape || _T("HEMISPHERICAL") == sShape
|| _T("INVSPHERICAL") == sShape || _T("INVHEMISPHERICAL") == sShape
|| _T("CURVED") == sShape || _T("INVCURVED") == sShape )
{
pathType type = Spherical;
float startPos = 0.65f;
if (_T("HEMISPHERICAL") == sShape || _T("INVHEMISPHERICAL") == sShape)
{
type = HemiSpherical;
startPos = 0.5f;
}
else if (_T("CURVED") == sShape || _T("INVCURVED") == sShape)
{
type = Curved;
startPos = 0.0f;
// 对于 曲线形,先用 color1 画底色
PathGradientBrush* pBrushCurve = new PathGradientBrush(&graphticPath);
pBrushCurve->SetCenterColor(color1);
Color clrs[] = { color1 };
int iCount = 1;
pBrushCurve->SetSurroundColors(clrs, &iCount);
graphics.FillPath(pBrushCurve, &graphticPath);
delete pBrushCurve;
}
PointF ptCenter;
bool isInCenter = (m_vbGCenInCen == VARIANT_TRUE) ? true : false;
GraphicsPath* pathCircle = GetEllipsePath(m_ptArray, i_nPtsNum, m_dGrdAngle, &ptCenter, type, isInCenter);
PathGradientBrush* pathGdBrush = new PathGradientBrush(pathCircle);
// 设置中心 周围 颜色
pathGdBrush->SetCenterPoint(ptCenter);
pathGdBrush->SetCenterColor(color2);
Color clrs[] = { color1 };
int iCount = 1;
pathGdBrush->SetSurroundColors(clrs, &iCount);
// 位置开始 startPos 为 1 份 剩下的等分成 24 等份
int numDiv = 24;
float* intensities = new float[numDiv + 1];
float* positions = new float[numDiv + 1];
intensities[0] = 0.0f;
positions[0] = 0.0f;
float angleDiv = (float)PI / 2.0 / (numDiv - 1);
float posDiv = (1 - startPos) / (numDiv - 1);
for (int i = 1; i < numDiv + 1; i++) // 1-13
{
intensities[i] = sin(angleDiv * (i - 1));
positions[i] = posDiv * (i - 1) + startPos;
}
pathGdBrush->SetBlend(intensities, positions, numDiv + 1);
delete[] intensities;
delete[] positions;
// 填充
//graphics.FillRectangle(pathGdBrush, 0, 0, 800, 800);
graphics.FillPath(pathGdBrush, &graphticPath);
delete pathCircle;
delete pathGdBrush;
return true;
}
return true;
}
渐变色画刷:线性渐变画刷/路径渐变画刷
最新推荐文章于 2023-12-26 13:23:00 发布