渐变色画刷:线性渐变画刷/路径渐变画刷

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值