📄 scdcrendpolys_i.cpp
字号:
/*
* 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 + -