mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-15 01:28:47 +08:00
171 lines
7.7 KiB
C++
171 lines
7.7 KiB
C++
#include "CPathConverter.h"
|
|
|
|
namespace MetaFile
|
|
{
|
|
CPathConverter::CPathConverter()
|
|
{}
|
|
|
|
CPathConverter::~CPathConverter()
|
|
{}
|
|
|
|
void CPathConverter::GetUpdatedPath(CEmfPath &oNewPath, CEmfPath &oLineCapPath, const CEmfPath &oPath, const CEmfPlusPen &oPen)
|
|
{
|
|
TEmfPlusPointF oLastPoint(0, 0);
|
|
|
|
for (const CEmfPathCommandBase* pCommand : oPath.m_pCommands)
|
|
{
|
|
switch (pCommand->GetType())
|
|
{
|
|
case EMF_PATHCOMMAND_UNKNOWN: break;
|
|
case EMF_PATHCOMMAND_MOVETO:
|
|
{
|
|
CEmfPathMoveTo *pCommandMoveTo = (CEmfPathMoveTo*)pCommand;
|
|
oNewPath.MoveTo(pCommandMoveTo->x, pCommandMoveTo->y);
|
|
|
|
oLastPoint.X = pCommandMoveTo->x;
|
|
oLastPoint.Y = pCommandMoveTo->y;
|
|
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_LINETO:
|
|
{
|
|
CEmfPathLineTo *pCommandLineTo = (CEmfPathLineTo*)pCommand;
|
|
|
|
double dAngle = -90 + (atan((pCommandLineTo->y - oLastPoint.Y) /
|
|
(pCommandLineTo->x - oLastPoint.X)) * 180 / 3.14);
|
|
|
|
if (AddLineStartCap(oLineCapPath, oPen, oLastPoint.X, oLastPoint.Y, dAngle + 180))
|
|
oNewPath.MoveTo(oLastPoint.X, oLastPoint.Y);
|
|
|
|
oLastPoint.X = pCommandLineTo->x;
|
|
oLastPoint.Y = pCommandLineTo->y;
|
|
|
|
AddLineEndCap(oLineCapPath, oPen, oLastPoint.X, oLastPoint.Y, dAngle);
|
|
|
|
oNewPath.LineTo(oLastPoint.X, oLastPoint.Y);
|
|
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_CURVETO:
|
|
{
|
|
CEmfPathCurveTo *pCommandCurveTo = (CEmfPathCurveTo*)pCommand;
|
|
|
|
oNewPath.CurveTo(pCommandCurveTo->x1, pCommandCurveTo->y1,
|
|
pCommandCurveTo->x2, pCommandCurveTo->y2,
|
|
pCommandCurveTo->xE, pCommandCurveTo->yE);
|
|
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_ARCTO:
|
|
{
|
|
CEmfPathArcTo *pCommandArcTo = (CEmfPathArcTo*)pCommand;
|
|
|
|
oNewPath.ArcTo(pCommandArcTo->left, pCommandArcTo->top,
|
|
pCommandArcTo->right, pCommandArcTo->bottom,
|
|
pCommandArcTo->start, pCommandArcTo->sweep);
|
|
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_CLOSE:
|
|
{
|
|
oNewPath.Close();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool CPathConverter::AddLineStartCap(CEmfPath &oPath, const CEmfPlusPen &oPen, double& dX, double& dY, double dAngle)
|
|
{
|
|
if (NULL != oPen.LineStartCapData)
|
|
{
|
|
if (CustomLineCapDataTypeDefault == oPen.LineStartCapData->GetType() && NULL != ((TEmfPlusCustomLineCapData*)oPen.LineStartCapData)->pPath)
|
|
{
|
|
return AddLineCap(oPath, ((TEmfPlusCustomLineCapData*)oPen.LineStartCapData)->pPath, dX, dY, dAngle, oPen.Width);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CPathConverter::AddLineEndCap(CEmfPath &oPath, const CEmfPlusPen &oPen, double &dX, double &dY, double dAngle)
|
|
{
|
|
if (NULL != oPen.LineEndCapData)
|
|
{
|
|
if (CustomLineCapDataTypeDefault == oPen.LineEndCapData->GetType() && NULL != ((TEmfPlusCustomLineCapData*)oPen.LineEndCapData)->pPath)
|
|
{
|
|
return AddLineCap(oPath, ((TEmfPlusCustomLineCapData*)oPen.LineEndCapData)->pPath, dX, dY, dAngle, oPen.Width);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CPathConverter::AddLineCap(CEmfPath &oPath, const CEmfPath &oLineCapPath, double &dX, double &dY, double dAngle, double dPenWidth)
|
|
{
|
|
double dNewX = 0;
|
|
double dNewY = 0;
|
|
|
|
double dSin = sin(dAngle * 3.14 / 180);
|
|
double dCos = cos(dAngle * 3.14 / 180);
|
|
|
|
for (const CEmfPathCommandBase* pCommand : oLineCapPath.m_pCommands)
|
|
{
|
|
switch (pCommand->GetType())
|
|
{
|
|
case EMF_PATHCOMMAND_UNKNOWN: break;
|
|
case EMF_PATHCOMMAND_MOVETO:
|
|
{
|
|
CEmfPathMoveTo *pCommandMoveTo = (CEmfPathMoveTo*)pCommand;
|
|
|
|
double dTempX = pCommandMoveTo->x * dPenWidth * dCos - pCommandMoveTo->y * dPenWidth * dSin;
|
|
double dTempY = pCommandMoveTo->x * dPenWidth * dSin + pCommandMoveTo->y * dPenWidth * dCos;
|
|
|
|
dNewX += dTempX;
|
|
dNewY += dTempY;
|
|
|
|
oPath.MoveTo(dX + dTempX, dY + dTempY);
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_LINETO:
|
|
{
|
|
CEmfPathLineTo *pCommandLineTo = (CEmfPathLineTo*)pCommand;
|
|
|
|
double dTempX = pCommandLineTo->x * dPenWidth * dCos - pCommandLineTo->y * dPenWidth * dSin;
|
|
double dTempY = pCommandLineTo->x * dPenWidth * dSin + pCommandLineTo->y * dPenWidth * dCos;
|
|
|
|
dNewX += dTempX;
|
|
dNewY += dTempY;
|
|
|
|
oPath.LineTo(dX + dTempX, dY + dTempY);
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_CURVETO:
|
|
{
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_ARCTO:
|
|
{
|
|
break;
|
|
}
|
|
case EMF_PATHCOMMAND_CLOSE:
|
|
{
|
|
oPath.Close();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (oPath.m_pCommands.size() > 1)
|
|
{
|
|
dX = dX + dNewX / (oPath.m_pCommands.size() - 1);
|
|
dY = dY + dNewY / (oPath.m_pCommands.size() - 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|