Fix Redact with shapes

This commit is contained in:
Svetlana Kulikova
2025-10-02 15:11:42 +03:00
parent 8cc18975b7
commit 0e68a83f0d
4 changed files with 109 additions and 71 deletions

View File

@ -906,7 +906,15 @@ HRESULT CPdfWriter::DrawPath(NSFonts::IApplicationFonts* pAppFonts, const std::w
}
if (!m_arrRedact.empty())
m_oPath.Redact(m_oTransform, m_arrRedact, bStroke, bEoFill);
{
PdfWriter::CMatrix* pMatrix = m_pPage->GetTransform();
m_oPath.Redact(pMatrix, m_arrRedact, m_pPage, bStroke, bFill, bEoFill, m_pShading, m_pShadingExtGrState);
m_pPage->GrRestore();
if (!sTextureTmpPath.empty())
m_oBrush.SetTexturePath(sTextureOldPath);
return S_OK;
}
if (!m_pShading)
{

View File

@ -297,9 +297,9 @@ bool SkipPath(const std::vector<PdfWriter::CSegment>& arrForStroke, const PdfWri
}
return false;
}
void CPath::DrawPathRedact(PdfWriter::CMatrix oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector<PdfWriter::CSegment>& arrForStroke)
void CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector<PdfWriter::CSegment>& arrForStroke)
{
PdfWriter::CMatrix oInverse = oMatrix.Inverse();
PdfWriter::CMatrix oInverse = pMatrix->Inverse();
size_t length = oPath->GetPointCount(), compound = oPath->GetCloseCount();
std::vector<Aggplus::PointD> points = oPath->GetPoints(0, length + compound);
@ -389,10 +389,10 @@ void CPath::DrawPathRedact(PdfWriter::CMatrix oMatrix, Aggplus::CGraphicsPath* o
}
}
}
void CPath::Redact(const CTransform& oTransform, const std::vector<double>& arrRedact, bool bStroke, bool bEoFill)
void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector<double>& arrRedact, PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill,
PdfWriter::CShading* pShading, PdfWriter::CExtGrState* pShadingExtGrState)
{
PdfWriter::CMatrix oMatrix(oTransform.m11, oTransform.m12, oTransform.m21, oTransform.m22, oTransform.dx, oTransform.dy);
PdfWriter::CMatrix oInverse = oMatrix.Inverse();
PdfWriter::CMatrix oInverse = pMatrix->Inverse();
Aggplus::CGraphicsPath oPath, oPathRedact, oPathResult;
for (int i = 0; i < arrRedact.size(); i += 4)
@ -405,15 +405,38 @@ void CPath::Redact(const CTransform& oTransform, const std::vector<double>& arrR
oPathRedact.CloseFigure();
}
for (int nIndex = 0, nCount = m_vCommands.size(); nIndex < nCount; nIndex++)
std::vector<CPathCommandBase*> vCommands = m_vCommands;
for (int nIndex = 0, nCount = vCommands.size(); nIndex < nCount; nIndex++)
{
CPathCommandBase* pCommand = m_vCommands.at(nIndex);
CPathCommandBase* pCommand = vCommands.at(nIndex);
// CPath to CGraphicsPath
pCommand->ToCGraphicsPath(oTransform, oPath);
pCommand->ToCGraphicsPath(pMatrix, oPath);
}
if (bEoFill)
oPath.SetRuler(true);
Clear();
m_vCommands.clear();
if (bFill || bEoFill)
{
oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction);
DrawPathRedact(pMatrix, &oPathResult, bStroke);
if (!pShading)
Draw(pPage, false, bFill, bEoFill);
else
{
pPage->GrSave();
Clip(pPage, bEoFill);
if (pShadingExtGrState)
pPage->SetExtGrState(pShadingExtGrState);
pPage->DrawShading(pShading);
pPage->GrRestore();
}
}
m_vCommands.clear();
if (bStroke)
{
@ -454,7 +477,7 @@ void CPath::Redact(const CTransform& oTransform, const std::vector<double>& arrR
dXCur = dX3, dYCur = dY3;
oPathResult = Aggplus::CalcBooleanOperation(_oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction);
DrawPathRedact(oMatrix, &oPathResult, bStroke, arrForStroke);
DrawPathRedact(pMatrix, &oPathResult, bStroke, arrForStroke);
oPathResult.Reset();
}
else if (oPath.IsMovePoint(i))
@ -497,12 +520,11 @@ void CPath::Redact(const CTransform& oTransform, const std::vector<double>& arrR
}
}
}
Draw(pPage, bStroke, false, false);
}
else
{
oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction);
DrawPathRedact(oMatrix, &oPathResult, bStroke);
}
m_vCommands = vCommands;
}
void CPath::Draw(PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill)
{
@ -582,10 +604,10 @@ void CPath::CPathMoveTo::UpdateBounds(double& dL, double& dT, double& dR, double
{
UpdateMaxMinPoints(dL, dT, dR, dB, x, y);
}
void CPath::CPathMoveTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void CPath::CPathMoveTo::ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
double dX, dY;
oTransform.Transform(x, y, &dX, &dY);
double dX = x, dY = y;
pMatrix->Apply(dX, dY);
oPath.StartFigure();
oPath.MoveTo(dX, dY);
}
@ -597,10 +619,10 @@ void CPath::CPathLineTo::UpdateBounds(double& dL, double& dT, double& dR, double
{
UpdateMaxMinPoints(dL, dT, dR, dB, x, y);
}
void CPath::CPathLineTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void CPath::CPathLineTo::ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
double dX, dY;
oTransform.Transform(x, y, &dX, &dY);
pMatrix->Transform(x, y, &dX, &dY);
oPath.LineTo(dX, dY);
}
void CPath::CPathCurveTo::Draw(PdfWriter::CPage* pPage)
@ -613,12 +635,12 @@ void CPath::CPathCurveTo::UpdateBounds(double& dL, double& dT, double& dR, doubl
UpdateMaxMinPoints(dL, dT, dR, dB, x2, y2);
UpdateMaxMinPoints(dL, dT, dR, dB, xe, ye);
}
void CPath::CPathCurveTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void CPath::CPathCurveTo::ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
double dX1, dY1, dX2, dY2, dX3, dY3;
oTransform.Transform(x1, y1, &dX1, &dY1);
oTransform.Transform(x2, y2, &dX2, &dY2);
oTransform.Transform(xe, ye, &dX3, &dY3);
pMatrix->Transform(x1, y1, &dX1, &dY1);
pMatrix->Transform(x2, y2, &dX2, &dY2);
pMatrix->Transform(xe, ye, &dX3, &dY3);
oPath.CurveTo(dX1, dY1, dX2, dY2, dX3, dY3);
}
void CPath::CPathArcTo::Draw(PdfWriter::CPage* pPage)
@ -640,7 +662,7 @@ double AngToEllPrm(double dAngle, double dXRad, double dYRad)
// x = r cos(p), y = r sin(p) => t = atan2( sin(p) / b, cos(p) / a );
return atan2(sin(dAngle) / dYRad, cos(dAngle) / dXRad);
}
void WriteEllipseArc(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath, double dX, double dY, double dXRad, double dYRad, double dAngle1, double dAngle2, double& dXCur, double& dYCur, bool bClockDirection = false)
void WriteEllipseArc(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath, double dX, double dY, double dXRad, double dYRad, double dAngle1, double dAngle2, double& dXCur, double& dYCur, bool bClockDirection = false)
{
// Рассчитаем начальную, конечную и контрольные точки
double dX1 = 0.0, dX2 = 0.0, dY1 = 0.0, dY2 = 0.0;
@ -666,9 +688,9 @@ void WriteEllipseArc(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath
dYCur = dY2;
double _dX1, _dY1, _dX2, _dY2, dX3, dY3;
oTransform.Transform(dCX1, dCY1, &_dX1, &_dY1);
oTransform.Transform(dCX2, dCY2, &_dX2, &_dY2);
oTransform.Transform(dX2, dY2, &dX3, &dY3);
pMatrix->Transform(dCX1, dCY1, &_dX1, &_dY1);
pMatrix->Transform(dCX2, dCY2, &_dX2, &_dY2);
pMatrix->Transform(dX2, dY2, &dX3, &dY3);
oPath.CurveTo(_dX1, _dY1, _dX2, _dY2, dX3, dY3);
}
else
@ -677,13 +699,13 @@ void WriteEllipseArc(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath
dYCur = dY1;
double _dX1, _dY1, _dX2, _dY2, dX3, dY3;
oTransform.Transform(dCX2, dCY2, &_dX1, &_dY1);
oTransform.Transform(dCX1, dCY1, &_dX2, &_dY2);
oTransform.Transform(dX1, dY1, &dX3, &dY3);
pMatrix->Transform(dCX2, dCY2, &_dX1, &_dY1);
pMatrix->Transform(dCX1, dCY1, &_dX2, &_dY2);
pMatrix->Transform(dX1, dY1, &dX3, &dY3);
oPath.CurveTo(_dX1, _dY1, _dX2, _dY2, dX3, dY3);
}
}
void EllipseArc(double dX, double dY, double dXRad, double dYRad, double _dAngle1, double _dAngle2, bool bClockDirection, const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void EllipseArc(double dX, double dY, double dXRad, double dYRad, double _dAngle1, double _dAngle2, bool bClockDirection, PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
// переведем углы в радианы
double dAngle1 = _dAngle1 * 3.141592f / 180;
@ -718,7 +740,7 @@ void EllipseArc(double dX, double dY, double dXRad, double dYRad, double _dAngle
if (!(nIndex == nFirstPointQuard))
dStartAngle = (90 * (nIndex - 1)) * 3.141592f / 180;
WriteEllipseArc(oTransform, oPath, dX, dY, dXRad, dYRad, AngToEllPrm(dStartAngle, dXRad, dYRad), AngToEllPrm(dEndAngle, dXRad, dYRad), dEndX, dEndY, false);
WriteEllipseArc(pMatrix, oPath, dX, dY, dXRad, dYRad, AngToEllPrm(dStartAngle, dXRad, dYRad), AngToEllPrm(dEndAngle, dXRad, dYRad), dEndX, dEndY, false);
}
}
else
@ -734,11 +756,11 @@ void EllipseArc(double dX, double dY, double dXRad, double dYRad, double _dAngle
else
dEndAngle = dAngle2;
WriteEllipseArc(oTransform, oPath, dX, dY, dXRad, dYRad, AngToEllPrm(dStartAngle, dXRad, dYRad), AngToEllPrm(dEndAngle, dXRad, dYRad), dEndX, dEndY, false);
WriteEllipseArc(pMatrix, oPath, dX, dY, dXRad, dYRad, AngToEllPrm(dStartAngle, dXRad, dYRad), AngToEllPrm(dEndAngle, dXRad, dYRad), dEndX, dEndY, false);
}
}
}
void CPath::CPathArcTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void CPath::CPathArcTo::ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
if (sweepAngle >= 360 - 0.001)
{
@ -750,28 +772,28 @@ void CPath::CPathArcTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::C
double dYRay = h / 2;
double _dX, _dY;
oTransform.Transform(dX, dY, &_dX, &_dY);
pMatrix->Transform(dX, dY, &_dX, &_dY);
oPath.MoveTo(_dX, _dY);
double dX1, dY1, dX2, dY2, dX3, dY3;
oTransform.Transform(dX - dXRay, dY + dYRay * c_dKappa, &dX1, &dY1);
oTransform.Transform(dX - dXRay * c_dKappa, dY + dYRay, &dX2, &dY2);
oTransform.Transform(dX, dY + dYRay, &dX3, &dY3);
pMatrix->Transform(dX - dXRay, dY + dYRay * c_dKappa, &dX1, &dY1);
pMatrix->Transform(dX - dXRay * c_dKappa, dY + dYRay, &dX2, &dY2);
pMatrix->Transform(dX, dY + dYRay, &dX3, &dY3);
oPath.CurveTo(dX1, dY1, dX2, dY2, dX3, dY3);
oTransform.Transform(dX + dXRay * c_dKappa, dY + dYRay, &dX1, &dY1);
oTransform.Transform(dX + dXRay, dY + dYRay * c_dKappa, &dX2, &dY2);
oTransform.Transform(dX + dXRay, dY, &dX3, &dY3);
pMatrix->Transform(dX + dXRay * c_dKappa, dY + dYRay, &dX1, &dY1);
pMatrix->Transform(dX + dXRay, dY + dYRay * c_dKappa, &dX2, &dY2);
pMatrix->Transform(dX + dXRay, dY, &dX3, &dY3);
oPath.CurveTo(dX1, dY1, dX2, dY2, dX3, dY3);
oTransform.Transform(dX + dXRay, dY - dYRay * c_dKappa, &dX1, &dY1);
oTransform.Transform(dX + dXRay * c_dKappa, dY - dYRay, &dX2, &dY2);
oTransform.Transform(dX, dY - dYRay, &dX3, &dY3);
pMatrix->Transform(dX + dXRay, dY - dYRay * c_dKappa, &dX1, &dY1);
pMatrix->Transform(dX + dXRay * c_dKappa, dY - dYRay, &dX2, &dY2);
pMatrix->Transform(dX, dY - dYRay, &dX3, &dY3);
oPath.CurveTo(dX1, dY1, dX2, dY2, dX3, dY3);
oTransform.Transform(dX - dXRay * c_dKappa, dY - dYRay, &dX1, &dY1);
oTransform.Transform(dX - dXRay, dY - dYRay * c_dKappa, &dX2, &dY2);
oTransform.Transform(dX - dXRay, dY, &dX3, &dY3);
pMatrix->Transform(dX - dXRay * c_dKappa, dY - dYRay, &dX1, &dY1);
pMatrix->Transform(dX - dXRay, dY - dYRay * c_dKappa, &dX2, &dY2);
pMatrix->Transform(dX - dXRay, dY, &dX3, &dY3);
oPath.CurveTo(dX1, dY1, dX2, dY2, dX3, dY3);
}
else
@ -787,21 +809,21 @@ void CPath::CPathArcTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::C
double _dX, _dY;
if (dXRad < 0.001 && dYRad < 0.001)
{
oTransform.Transform(dX, dY, &_dX, &_dY);
pMatrix->Transform(dX, dY, &_dX, &_dY);
oPath.LineTo(_dX, _dY);
}
else if (dXRad < 0.001)
{
oTransform.Transform(dX, dY + sin(dAngle1) * dYRad, &_dX, &_dY);
pMatrix->Transform(dX, dY + sin(dAngle1) * dYRad, &_dX, &_dY);
oPath.LineTo(_dX, _dY);
oTransform.Transform(dX, dY + sin(dAngle2) * dYRad, &_dX, &_dY);
pMatrix->Transform(dX, dY + sin(dAngle2) * dYRad, &_dX, &_dY);
oPath.LineTo(_dX, _dY);
}
else // if (dYRad < 0.001)
{
oTransform.Transform(dX + cos(dAngle1) * dXRad, dY, &_dX, &_dY);
pMatrix->Transform(dX + cos(dAngle1) * dXRad, dY, &_dX, &_dY);
oPath.LineTo(_dX, _dY);
oTransform.Transform(dX + cos(dAngle2) * dXRad, dY, &_dX, &_dY);
pMatrix->Transform(dX + cos(dAngle2) * dXRad, dY, &_dX, &_dY);
oPath.LineTo(_dX, _dY);
}
return;
@ -822,21 +844,21 @@ void CPath::CPathArcTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::C
if (!bClockDirection)
{
if (_dAngle1 <= _dAngle2)
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, _dAngle2, false, oTransform, oPath);
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, _dAngle2, false, pMatrix, oPath);
else
{
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, 360, false, oTransform, oPath);
EllipseArc(dX, dY, dXRad, dYRad, 0, _dAngle2, false, oTransform, oPath);
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, 360, false, pMatrix, oPath);
EllipseArc(dX, dY, dXRad, dYRad, 0, _dAngle2, false, pMatrix, oPath);
}
}
else
{
if (_dAngle1 >= _dAngle2)
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, _dAngle2, true, oTransform, oPath);
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, _dAngle2, true, pMatrix, oPath);
else
{
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, 0, true, oTransform, oPath);
EllipseArc(dX, dY, dXRad, dYRad, 360, _dAngle2, true, oTransform, oPath);
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, 0, true, pMatrix, oPath);
EllipseArc(dX, dY, dXRad, dYRad, 360, _dAngle2, true, pMatrix, oPath);
}
}
}
@ -848,7 +870,7 @@ void CPath::CPathClose::Draw(PdfWriter::CPage* pPage)
void CPath::CPathClose::UpdateBounds(double& dL, double& dT, double& dR, double& dB)
{
}
void CPath::CPathClose::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void CPath::CPathClose::ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
oPath.CloseFigure();
}
@ -866,7 +888,7 @@ void CPath::CPathText::UpdateBounds(double& dL, double& dT, double& dR, double&
{
UpdateMaxMinPoints(dL, dT, dR, dB, x, y);
}
void CPath::CPathText::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
void CPath::CPathText::ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath)
{
// Весь текст проверяется в CPdfWriter::PathCommandDrawText
// Эта функция не должна быть вызвана

View File

@ -45,6 +45,8 @@ namespace PdfWriter
{
class CPage;
class CFontDict;
class CShading;
class CExtGrState;
}
class CPdfWriter;
@ -1343,7 +1345,7 @@ private:
virtual void UpdateBounds(double& dL, double& dT, double& dR, double& dB) = 0;
virtual void GetLastPoint(double& dX, double& dY) = 0;
virtual EPathCommandType GetType() = 0;
virtual void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath) = 0;
virtual void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath) = 0;
};
class CPathMoveTo : public CPathCommandBase
{
@ -1364,7 +1366,7 @@ private:
{
return rendererpathcommand_MoveTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath);
public:
@ -1390,7 +1392,7 @@ private:
{
return rendererpathcommand_LineTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath);
public:
@ -1420,7 +1422,7 @@ private:
{
return rendererpathcommand_CurveTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath);
public:
@ -1455,7 +1457,7 @@ private:
{
return rendererpathcommand_ArcTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath);
public:
@ -1484,7 +1486,7 @@ private:
{
return rendererpathcommand_Close;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath);
};
class CPathText : public CPathCommandBase
{
@ -1514,7 +1516,7 @@ private:
{
return rendererpathcommand_Text;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
void ToCGraphicsPath(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath& oPath);
public:
@ -1590,8 +1592,9 @@ public:
void Draw(PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill);
void Clip(PdfWriter::CPage* pPage, bool bEvenOdd = false);
void GetBounds(double& dL, double& dT, double& dR, double& dB);
void Redact(const CTransform& oTransform, const std::vector<double>& arrRedact, bool bStroke, bool bEoFill);
void DrawPathRedact(PdfWriter::CMatrix oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector<PdfWriter::CSegment>& arrForStroke = {});
void Redact(PdfWriter::CMatrix* oMatrix, const std::vector<double>& arrRedact, PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill,
PdfWriter::CShading* pShading, PdfWriter::CExtGrState* pShadingExtGrState);
void DrawPathRedact(PdfWriter::CMatrix* oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector<PdfWriter::CSegment>& arrForStroke = {});
private:

View File

@ -131,6 +131,11 @@ namespace PdfWriter
dX = _x * m11 + _y * m21 + x;
dY = _x * m12 + _y * m22 + y;
}
void Transform(double dUserX, double dUserY, double* pdDeviceX, double* pdDeviceY) const
{
*pdDeviceX = dUserX * m11 + dUserY * m21 + x;
*pdDeviceY = dUserX * m12 + dUserY * m22 + y;
}
bool operator==(const CMatrix& oMatrix)
{
if (fabs(oMatrix.m11 - m11) > 0.001