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