⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scdcrendpolys_i.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	double dStartAngle;
	double dSweepAngle;
	SCBuildArcAngles(pBox, pPtStart, pPtEnd, m_dwArcDirection, dStartAngle, dSweepAngle);

	Rect rect;
	SCNormalizedRectFromRECT(&rect, (LPCRECT)pBox);
	if (m_pPath)
		m_pPath->AddArc(rect, (REAL)dStartAngle, (REAL)dSweepAngle);
	else
	{
		ASSERT(m_pPen);
		m_pGraphics->DrawArc(m_pPen, rect, (REAL)dStartAngle, (REAL)dSweepAngle);
	}
}

void CSCEMFdcRenderer::SCDrawArcTo(LPCRECTL pBox, LPCPOINTL pPtStart, LPCPOINTL pPtEnd)
{
	ASSERT(m_pGraphics);
	ASSERT(pBox);

	double dStartAngle;
	double dSweepAngle;
	SCBuildArcAngles(pBox, pPtStart, pPtEnd, m_dwArcDirection, dStartAngle, dSweepAngle);

	Rect rect;
	SCNormalizedRectFromRECT(&rect, (LPCRECT)pBox);
	if (m_pPath)
		m_pPath->AddEllipse(rect);
	else
	{
		ASSERT(m_pPen);
		m_pGraphics->DrawArc(m_pPen, rect, (REAL)dStartAngle, (REAL)dSweepAngle);
	}
}


void CSCEMFdcRenderer::SCDrawChord(LPCRECTL pBox, LPCPOINTL pPtStart, LPCPOINTL pPtEnd)
{
	ASSERT(m_pGraphics);
	ASSERT(pBox);

	double dStartAngle;
	double dSweepAngle;
	SCBuildArcAngles(pBox, pPtStart, pPtEnd, m_dwArcDirection, dStartAngle, dSweepAngle);

	Rect rect;
	SCNormalizedRectFromRECT(&rect, (LPCRECT)pBox);
#if 0
	// Functions are missing!
	// Good place to say: GDI+ does not work!
	if (m_pPath)
		m_pPath->AddChord(rect, dStartAngle, dSweepAngle);
	else
	{
		// TODO: Fill shape by using the current brush
		if (m_pBrush)
			m_pGraphics->FillChord(m_pBrush, rect, dStartAngle, dSweepAngle);

		if (m_pPen)
			m_pGraphics->DrawChord(m_pPen, rect, dStartAngle, dSweepAngle);
	}
#else
	GraphicsPath NewPath;
	NewPath.AddArc(rect, (REAL)dStartAngle, (REAL)dSweepAngle);

	Point PtStart;
	Point PtEnd;

	SCIntersectLineAndEllipse(PtStart, pBox, dStartAngle);
	SCIntersectLineAndEllipse(PtEnd, pBox, dStartAngle+dSweepAngle);
	NewPath.AddLine(PtStart, PtEnd);

	if (m_pPath)
		m_pPath->AddPath(&NewPath, FALSE);
	else
	{
		// Fill shape by using the current brush
		if (m_pBrush)
		{
			FillMode fillMode = (ALTERNATE==m_dwFillMode) ? FillModeAlternate : FillModeWinding;
			NewPath.SetFillMode(fillMode);
			m_pGraphics->FillPath(m_pBrush, &NewPath);
		}
		// Note: there is a pen size issue here (corners look thinner than straight lines)
		// And background color is seen outside the corners limit.
		if (m_pPen)
			m_pGraphics->DrawPath(m_pPen, &NewPath);
	}
#endif
}

void CSCEMFdcRenderer::SCDrawPie(LPCRECTL pBox, LPCPOINTL pPtStart, LPCPOINTL pPtEnd)
{
	ASSERT(m_pGraphics);
	ASSERT(pBox);

	double dStartAngle;
	double dSweepAngle;
	SCBuildArcAngles(pBox, pPtStart, pPtEnd, m_dwArcDirection, dStartAngle, dSweepAngle);

	Rect rect;
	SCNormalizedRectFromRECT(&rect, (LPCRECT)pBox);
	if (m_pPath)
		m_pPath->AddPie(rect, (REAL)dStartAngle, (REAL)dSweepAngle);
	else
	{
		// Fill shape by using the current brush
		if (m_pBrush)
			m_pGraphics->FillPie(m_pBrush, rect, (REAL)dStartAngle, (REAL)dSweepAngle);

		if (m_pPen)
			m_pGraphics->DrawPie(m_pPen, rect, (REAL)dStartAngle, (REAL)dSweepAngle);
	}
}

///
///	The AngleArc function draws a line segment and an arc.
///	The line segment is drawn from the current position to the beginning of the arc.
///	The arc is drawn along the perimeter of a circle with the given radius and center.
///	The length of the arc is defined by the given start and sweep angles
///	Angles are given in degrees and relative to the x-axis.
/// NOTE: The figure is not filled.
///
void CSCEMFdcRenderer::SCDrawAngleArc(POINT* pPtCenter, DWORD dwRadius, FLOAT fStartAngle, FLOAT fSweepAngle)
{
	ASSERT(m_pGraphics);
	ASSERT(pPtCenter);

	// Compute points of the line segment
	Point Pt1(m_PtCurPos.X, m_PtCurPos.Y);

	Point Pt2;
	SCIntersectLineAndCircle(Pt2, (POINTL*)pPtCenter, dwRadius, fStartAngle);

	// Compute the rectangle that bounds the ellipse that contains the arc
	Rect rcCircle(pPtCenter->x - dwRadius, pPtCenter->y - dwRadius, 2*dwRadius, 2*dwRadius);
	if (m_pPath)
	{
		// a line segment from the current position to the beginning of the arc
		m_pPath->AddLine(Pt1, Pt2);

		// + an arc along the perimeter of a circle with the given radius and center
		m_pPath->AddArc(rcCircle, fStartAngle, fSweepAngle);
	} else
	{
		ASSERT(m_pPen);
		m_pGraphics->DrawLine(m_pPen, Pt1, Pt2);
		m_pGraphics->DrawArc(m_pPen, rcCircle, fStartAngle, fSweepAngle);
	}

	// Update the current position
	SCIntersectLineAndCircle(m_PtCurPos, (POINTL*)pPtCenter, dwRadius, fStartAngle + fSweepAngle);
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Shapes filling
///

///
///	Gradient fill of rectangles or triangles.
///
void CSCEMFdcRenderer::SCGradientFill(TRIVERTEX* pVer, DWORD dwCountVer, LPCBYTE pMesh, DWORD dwCountMesh, DWORD dwMode)
{
	ASSERT(m_pGraphics);
	if (m_pPath)
	{// Normally, GDI doesn't support gradient fill in a path
		ASSERT(0);
	} else
	{
		// The color information of each channel is specified as a value
		// from 0x0000 to 0xff00. We must translate to the (0x00, 0xFF) range
		#define SC_XTOWIN_CHANNEL(XChannel) MulDiv(XChannel, 0x00FF, 0xFF00)
		// And for GDI+ alpha==0 is transparent
		#define SC_XTOWIN_ALPHA(XChannel) (255 - MulDiv(XChannel, 0x00FF, 0xFF00))

		switch (dwMode)
		{
		case GRADIENT_FILL_RECT_H:
		case GRADIENT_FILL_RECT_V:
			{
				LinearGradientMode iMode = (GRADIENT_FILL_RECT_V==dwMode) ? LinearGradientModeVertical : LinearGradientModeHorizontal;
				GRADIENT_RECT *pRects = (GRADIENT_RECT*)pMesh;
				for (DWORD i=0; (i<dwCountMesh); i++)
				{
					TRIVERTEX* pv = &pVer[pRects[i].UpperLeft];
					Point Pt1(pv->x, pv->y);
					Color color1(
						SC_XTOWIN_ALPHA(pv->Alpha),
						SC_XTOWIN_CHANNEL(pv->Red),
						SC_XTOWIN_CHANNEL(pv->Green),
						SC_XTOWIN_CHANNEL(pv->Blue));
					
					pv = &pVer[pRects[i].LowerRight];
					Color color2(
						SC_XTOWIN_ALPHA(pv->Alpha),
						SC_XTOWIN_CHANNEL(pv->Red),
						SC_XTOWIN_CHANNEL(pv->Green),
						SC_XTOWIN_CHANNEL(pv->Blue));
					
					// rect including the contour
					Rect rcMesh(Pt1.X - 1, Pt1.Y - 1, pv->x - Pt1.X + 2, pv->y - Pt1.Y + 2);
					LinearGradientBrush brush(rcMesh, color1, color2, iMode);
					m_pGraphics->FillRectangle(&brush, rcMesh);
				}
			}
			break;

		case GRADIENT_FILL_TRIANGLE:
			{
				#define SC_USE_RECTANGLE

				GRADIENT_TRIANGLE *pTriangles = (GRADIENT_TRIANGLE *)pMesh;
				for (DWORD i=0; (i<dwCountMesh); i++)
				{
					// compute the colors
					Point points[3];
					Color colors[3];
					INT iCenterAlpha=0, iCenterR=0, iCenterG=0, iCenterB=0;
#ifndef SC_USE_RECTANGLE
					INT xMin=LONG_MAX, xMax=LONG_MIN, yMin=LONG_MAX, yMax=LONG_MIN;
#endif

					TRIVERTEX* pv;
					ULONG* pTri = (ULONG*)&pTriangles[i].Vertex1; // beware of structure packing!
					for (INT j=0; (j<3); j++)
					{
						pv = &pVer[pTri[j]];
						points[j].X = pv->x;
						points[j].Y = pv->y;
						colors[j] = Color::MakeARGB(
							SC_XTOWIN_ALPHA(pv->Alpha),
							SC_XTOWIN_CHANNEL(pv->Red),
							SC_XTOWIN_CHANNEL(pv->Green),
							SC_XTOWIN_CHANNEL(pv->Blue));
						iCenterAlpha += pv->Alpha;
						iCenterR += pv->Red;
						iCenterG += pv->Green;
						iCenterB += pv->Blue;

#ifndef SC_USE_RECTANGLE
						if (pv->x<xMin)
							xMin=pv->x;
						else
						if (pv->x>xMax)
							xMax=pv->x;

						if (pv->y<yMin)
							yMin=pv->y;
						else
						if (pv->y>yMax)
							yMax=pv->y;
#endif
					}

					Color colorCenter = Color::MakeARGB(
						SC_XTOWIN_ALPHA(iCenterAlpha/3),
						SC_XTOWIN_CHANNEL(iCenterR/3),
						SC_XTOWIN_CHANNEL(iCenterG/3),
						SC_XTOWIN_CHANNEL(iCenterB/3));
					
					// construct the brush
					PathGradientBrush pthGrBrush(points, 3);

					int count = 3;
					pthGrBrush.SetSurroundColors(colors, &count);
					pthGrBrush.SetCenterColor(colorCenter);

					// paint
					// include the contour
#ifdef SC_USE_RECTANGLE
					Rect rcMesh;
					pthGrBrush.GetRectangle(&rcMesh);
					rcMesh.Inflate(1, 1);
					m_pGraphics->FillRectangle(&pthGrBrush, rcMesh);
#else
					for (INT k=0; (k<3); k++)
					{
						if (points[k].X==xMin)
							points[k].X--;
						else
						if (points[k].X==xMax)
							points[k].X++;

						if (points[k].Y==yMin)
							points[k].Y--;
						else
						if (points[k].Y==yMax)
							points[k].Y++;
					}
					m_pGraphics->FillPolygon(&pthGrBrush, points, 3);
#endif
				}
			}
			break;
		}
	}
}

///
///	Fill an area with the current brush.
/// (rare occurrences in metafiles)
///
void CSCEMFdcRenderer::SCFloodFill(POINTL& rPtStart, COLORREF crColor, DWORD iMode)
{
	ASSERT(m_pGraphics);
	ASSERT(m_pBrush);

	// Panic! GDI+ can't do it.
	// Note, my son, you don't have to provide device independency
	// by just cutting off functions that exist in GDI: this is not polite.

	// Let's ask GDI (we won't waste our time in using lockbits; rare occurrences)
	HDC hOutputDC = m_pGraphics->GetHDC(); // we never use m_hDC for writing
	ASSERT(hOutputDC);
	if (!hOutputDC)
		return;

	HBRUSH hBrush = NULL;
	Color BrushColor;
	switch(m_pBrush->GetType())
	{
	case BrushTypeSolidColor:
		((SolidBrush*)m_pBrush)->GetColor(&BrushColor);
		hBrush = CreateSolidBrush(BrushColor.ToCOLORREF());
		break;
		
	case BrushTypeHatchFill:
		((HatchBrush*)m_pBrush)->GetBackgroundColor(&BrushColor);
		hBrush = CreateSolidBrush(BrushColor.ToCOLORREF());
		break;
		
	default:
		ASSERT(0);
	}

	if (hBrush)
	{
		HBRUSH hOldBrush = (HBRUSH)SelectObject(hOutputDC, hBrush);

		ExtFloodFill(hOutputDC, rPtStart.x, rPtStart.y, crColor, iMode);

		SelectObject(hOutputDC, hOldBrush);
		DeleteObject(hBrush);
	}
	m_pGraphics->ReleaseHDC(hOutputDC);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -