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

📄 scdcrendpolys_i.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
*	This file is part of the EMFexplorer projet.
*	Copyright (C) 2004 Smith Charles.
*
*	This library is free software; you can redistribute it and/or
*	modify it under the terms of the GNU Lesser General Public
*	License as published by the Free Software Foundation; either
*	version 2.1 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with this library; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
*
*	Extension: for commercial use, apply the Equity Public License, which
*	adds to the normal terms of the GLPL a condition of donation to the author.
*   If you are interested in support for this source code,
*   contact Smith Charles <smith.charles@free.fr> for more information.
*/


#include "stdafx.h"
#include "SCEMFdcRenderer.h"

using namespace Gdiplus;

///////////////////////////////////////////////////////////////////////////////////////
// Polygons/Polypolygons/Geometric shapes management
///////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////
// Polygons/Polypolygons
//

///
///	Draw a polygon, using current pen and brush in the spirit of GDI. 32-bit points.
///
void CSCEMFdcRenderer::SCDrawPolygon(POINT* pPoints, DWORD dwCount)
{
	T_SCDrawPolygon(pPoints, dwCount);
}

///
///	Draw a polygon, using current pen and brush in the spirit of GDI. 16-bit points.
///
void CSCEMFdcRenderer::SCDrawPolygonS(POINTS* pPoints, DWORD dwCount)
{
	T_SCDrawPolygon(pPoints, dwCount);
}

// In fact, it is not sure that inlining will take effect
template <class T>
inline void CSCEMFdcRenderer::T_SCDrawPolygon(T* pPoints, DWORD dwCount)
{
	ASSERT(m_pGraphics);

	Point* Pts = SCPointFromPOINT(pPoints, dwCount);
	if (m_pPath)
		m_pPath->AddPolygon(Pts, dwCount);
	else
	{
		if (m_pBrush)
		{
			FillMode fillMode = (ALTERNATE==m_dwFillMode) ? FillModeAlternate : FillModeWinding;
			m_pGraphics->FillPolygon(m_pBrush, Pts, dwCount, fillMode);
		}

		if (m_pPen)
			m_pGraphics->DrawPolygon(m_pPen, Pts, dwCount);
#if 1
		else
		if (m_pBrush)
		{// Potential bug here.
		 // Reason for this code is: FillPolygon only fills the interior of polygons
		 // (the border of a polygon is not filled, making holes in gradient layouts)
			switch(m_pBrush->GetType())
			{
			case BrushTypeSolidColor:
				{
					Color BrushColor;
					((SolidBrush*)m_pBrush)->GetColor(&BrushColor);
					Pen tmpPen(BrushColor, 1);
					m_pGraphics->DrawPolygon(&tmpPen, Pts, dwCount);
				}
				break;
			}
		}
#endif
	}
	delete [] Pts;
	// update current position
	SCUpdateCurPos(pPoints[dwCount-1].x, pPoints[dwCount-1].y);
}

void CSCEMFdcRenderer::SCDrawPolyPolygon(POINT* pPoints, DWORD dwCount, DWORD *pPolyVertices, DWORD dwNbPolys)
{
	T_SCDrawPolyPoly(pPoints, dwCount, pPolyVertices, dwNbPolys, FALSE);
}

void CSCEMFdcRenderer::SCDrawPolyPolygonS(POINTS* pPoints, DWORD dwCount, DWORD *pPolyVertices, DWORD dwNbPolys)
{
	T_SCDrawPolyPoly(pPoints, dwCount, pPolyVertices, dwNbPolys, FALSE);
}

void CSCEMFdcRenderer::SCDrawPolyPolyline(POINT* pPoints, DWORD dwCount, DWORD *pPolyVertices, DWORD dwNbPolys)
{
	T_SCDrawPolyPoly(pPoints, dwCount, pPolyVertices, dwNbPolys, TRUE);
}

void CSCEMFdcRenderer::SCDrawPolyPolylineS(POINTS* pPoints, DWORD dwCount, DWORD *pPolyVertices, DWORD dwNbPolys)
{
	T_SCDrawPolyPoly(pPoints, dwCount, pPolyVertices, dwNbPolys, TRUE);
}

template <class T>
inline void CSCEMFdcRenderer::T_SCDrawPolyPoly(T* pPoints, DWORD dwCount, DWORD *pPolyVertices, DWORD dwNbPolys, BOOL bLines)
{
	ASSERT(m_pGraphics);

	Point* Pts = SCPointFromPOINT(pPoints, dwCount);
	Point* pPolyPts = Pts;
	if (m_pPath)
	{
		if (bLines)
		{
			for (DWORD j=0; (j<dwNbPolys); j++)
			{
				m_pPath->AddLines(pPolyPts, pPolyVertices[j]);
				pPolyPts += pPolyVertices[j];
			}
		} else
		{
			for (DWORD j=0; (j<dwNbPolys); j++)
			{
				m_pPath->AddPolygon(pPolyPts, pPolyVertices[j]);
				pPolyPts += pPolyVertices[j];
			}
		}
	} else
	{	
		if (bLines)
		{
			ASSERT(m_pPen);
			if (m_pPen)
			{
				for (DWORD j=0; (j<dwNbPolys); j++)
				{
					m_pGraphics->DrawLines(m_pPen, pPolyPts, pPolyVertices[j]);
					pPolyPts += pPolyVertices[j];
				}
			}
		} else
		{
			if (m_pBrush)
			{// Anyway, GDI+ is not powerful enough to do correct alternate filling in this case

					// So we must do something
				if (WINDING==m_dwFillMode)
				{
					// Every area will be 'winded'
					for (DWORD j=0; (j<dwNbPolys); j++)
					{
						m_pGraphics->FillPolygon(m_pBrush, pPolyPts, pPolyVertices[j], FillModeWinding);
						pPolyPts += pPolyVertices[j];
					}
				} else
				{
					// Fill with a special data arrangement
					DWORD dwNewNbPolys = dwNbPolys;
					DWORD* pNewVertices = new DWORD[dwNewNbPolys];
					for (DWORD i=0; (i<dwNewNbPolys); i++)
						pNewVertices[i] = pPolyVertices[i];
					
					Point* pNewPoints = SCConvertPolyPoly(Pts, dwCount, pNewVertices, dwNewNbPolys);
					pPolyPts = pNewPoints;
					for (DWORD j=0; (j<dwNewNbPolys); j++)
					{
						m_pGraphics->FillPolygon(m_pBrush, pPolyPts, pNewVertices[j], FillModeAlternate);
						pPolyPts += pNewVertices[j];
					}
					delete [] pNewPoints;
					delete [] pNewVertices;
				}
			}

			if (m_pPen)
			{
				// Stroke with old data
				pPolyPts = Pts;
				for (DWORD j=0; (j<dwNbPolys); j++)
				{
					m_pGraphics->DrawPolygon(m_pPen, pPolyPts, pPolyVertices[j]);
					pPolyPts += pPolyVertices[j];
				}
			}
		}
	}
	delete [] Pts;
	// update current position
	SCUpdateCurPos(pPoints[dwCount-1].x, pPoints[dwCount-1].y);
}

void CSCEMFdcRenderer::SCDrawPolyDraw(POINT* pPoints, DWORD dwCount, BYTE *pTypes)
{
	T_SCDrawPolyDraw(pPoints, dwCount, pTypes);
}

void CSCEMFdcRenderer::SCDrawPolyDrawS(POINTS* pPoints, DWORD dwCount, BYTE *pTypes)
{
	T_SCDrawPolyDraw(pPoints, dwCount, pTypes);
}

template <class T>
inline void CSCEMFdcRenderer::T_SCDrawPolyDraw(T* pPoints, DWORD dwCount, BYTE *pTypes)
{
	ASSERT(m_pGraphics);

	Point* pNewPts = SCPointFromPOINT(pPoints, dwCount);
	BYTE* pNewTypes = SCPathPointTypesFROMCurveTypes(pTypes, dwCount);

	FillMode fillMode = (ALTERNATE==m_dwFillMode) ? FillModeAlternate : FillModeWinding;
	GraphicsPath NewPath(pNewPts, pNewTypes, dwCount, fillMode);

	if (m_pPath)
	{
		m_pPath->AddPath(&NewPath, FALSE);
	} else
	{
		ASSERT(m_pPen);
		if (m_pPen)
			m_pGraphics->DrawPath(m_pPen, &NewPath);
	}
	delete [] pNewPts;
	delete [] pNewTypes;
	// update current position
	SCUpdateCurPos(pPoints[dwCount-1].x, pPoints[dwCount-1].y);
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Geometric shapes (rectangles, ellipses, arcs)
///
void CSCEMFdcRenderer::SCDrawRectangle(LPCRECT pBox)
{
	ASSERT(m_pGraphics);
	ASSERT(pBox);

	// GDI+ can't draw twisted rects. We must normalize
	Rect rect;
	SCNormalizedRectFromRECT(&rect, pBox);

	if (m_pPath)
		m_pPath->AddRectangle(rect);
	else
	{
		// Fill shape by using the current brush
		if (m_pBrush)
			m_pGraphics->FillRectangle(m_pBrush, rect);
		if (m_pPen)
			m_pGraphics->DrawRectangle(m_pPen, rect);
	}
}

// Good place to say: GDI+ does not work!
void CSCEMFdcRenderer::SCDrawRoundRectangle(LPCRECT pBox, SIZE szlCorner)
{
	ASSERT(m_pGraphics);
	ASSERT(pBox);

	// GDI+ can't draw twisted rects. We must normalize
	RECT rc;
	SCGetNormalizedRect(&rc, pBox);

	// Make up points, numbered from LT and going clockwise (LT,RT,RB,LB,LT)
	Point Pts[8];
	INT iRx = szlCorner.cx/2;
	INT iRy = szlCorner.cy/2;

		// up-down and from left to right
	Pts[0].Y = Pts[1].Y = rc.top;
	Pts[7].Y = Pts[2].Y = rc.top + iRy;
	Pts[6].Y = Pts[3].Y = rc.bottom - iRy;
	Pts[5].Y = Pts[4].Y = rc.bottom;
		
		// from left to right and up-down
	Pts[7].X = Pts[6].X = rc.left;
	Pts[0].X = Pts[5].X = rc.left + iRx;
	Pts[1].X = Pts[4].X = rc.right - iRx;
	Pts[2].X = Pts[3].X = rc.right;

	INT iXRight = rc.right - szlCorner.cx;
	INT iYBottom = rc.bottom - szlCorner.cy;

	GraphicsPath NewPath;
	NewPath.AddLine(Pts[0], Pts[1]);
	NewPath.AddArc(iXRight, rc.top, szlCorner.cx, szlCorner.cy, 270, 90);

	NewPath.AddLine(Pts[2], Pts[3]);
	NewPath.AddArc(iXRight, iYBottom, szlCorner.cx, szlCorner.cy, 0, 90);

	NewPath.AddLine(Pts[4], Pts[5]);
	NewPath.AddArc(rc.left, iYBottom, szlCorner.cx, szlCorner.cy, 90, 90);

	NewPath.AddLine(Pts[6], Pts[7]);
	NewPath.AddArc(rc.left, rc.top, szlCorner.cx, szlCorner.cy, 180, 90);

	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);
	}
}

void CSCEMFdcRenderer::SCDrawEllipse(LPCRECT pBox)
{
	ASSERT(m_pGraphics);
	ASSERT(pBox);
	Rect rect;
	SCNormalizedRectFromRECT(&rect, pBox);
	if (m_pPath)
		m_pPath->AddEllipse(rect);
	else
	{
		// Fill shape by using the current brush
		if (m_pBrush)
			m_pGraphics->FillEllipse(m_pBrush, rect);
		if (m_pPen)
			m_pGraphics->DrawEllipse(m_pPen, rect);
	}
}

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

⌨️ 快捷键说明

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