Use Aggplus::CalcBooleanOperation

This commit is contained in:
Svetlana Kulikova
2025-09-26 15:56:29 +03:00
parent 21a166208f
commit a873787fd7
8 changed files with 263 additions and 179 deletions

View File

@ -946,7 +946,7 @@ namespace NSOnlineOfficeBinToPdf
if ((IAdvancedCommand::AdvancedCommandType::Undefined != eAdvancedCommandType) &&
(S_OK == pRenderer->IsSupportAdvancedCommand(eAdvancedCommandType)))
{
IAdvancedCommand* pCommand = oReader.Read(eCommand, pCorrector);
IAdvancedCommand* pCommand = oReader.Read(eCommand, pCorrector, nLen);
if (pCommand)
{
pRenderer->AdvancedCommand(pCommand);

View File

@ -3298,6 +3298,10 @@ bool CPdfEditor::EditWidgets(IAdvancedCommand* pCommand)
if (m_nMode == Mode::Unknown && !IncrementalUpdates())
return false;
WriteRedact({});
m_pWriter->AddRedact({});
m_arrRedact.clear();
CWidgetsInfo* pFieldInfo = (CWidgetsInfo*)pCommand;
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();

View File

@ -1334,7 +1334,6 @@ HRESULT CPdfFile::AdvancedCommand(IAdvancedCommand* command)
m_pInternal->pEditor->AddShapeXML(pCommand->GetShapeXML());
arrRedact = m_pInternal->pEditor->WriteRedact(pCommand->GetRedactID());
}
// TODO Здесь необходимо наложить на рендер области редактов
return m_pInternal->pWriter->AddRedact(arrRedact);
}
case IAdvancedCommand::AdvancedCommandType::ShapeEnd:

View File

@ -903,6 +903,9 @@ HRESULT CPdfWriter::DrawPath(NSFonts::IApplicationFonts* pAppFonts, const std::w
UpdateBrush(pAppFonts, wsTempDirectory);
}
if (!m_arrRedact.empty())
m_oPath.Redact(m_oTransform, m_arrRedact);
if (!m_pShading)
{
m_oPath.Draw(m_pPage, bStroke, bFill, bEoFill);
@ -1076,26 +1079,9 @@ HRESULT CPdfWriter::DrawImage(IGrObject* pImage, const double& dX, const double&
{
m_oCommandManager.Flush();
if (!IsPageValid() || !pImage)
if (!IsPageValid() || !pImage || SkipRedact(dX, dY, dW, dH))
return S_OK;
if (!m_arrRedact.empty())
{
double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY);
m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin);
m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax);
for (int i = 0; i < m_arrRedact.size(); i += 4)
{
double xMin = m_arrRedact[i + 0];
double yMin = m_arrRedact[i + 1];
double xMax = m_arrRedact[i + 2];
double yMax = m_arrRedact[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return S_OK;
}
}
if (!DrawImage((Aggplus::CImage*)pImage, dX, dY, dW, dH, 255))
return S_FALSE;
@ -1105,26 +1091,9 @@ HRESULT CPdfWriter::DrawImageFromFile(NSFonts::IApplicationFonts* pAppFonts, con
{
m_oCommandManager.Flush();
if (!IsPageValid())
if (!IsPageValid() || SkipRedact(dX, dY, dW, dH))
return S_OK;
if (!m_arrRedact.empty())
{
double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY);
m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin);
m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax);
for (int i = 0; i < m_arrRedact.size(); i += 4)
{
double xMin = m_arrRedact[i + 0];
double yMin = m_arrRedact[i + 1];
double xMax = m_arrRedact[i + 2];
double yMax = m_arrRedact[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return S_OK;
}
}
if (m_pDocument->HasImage(wsImagePathSrc, nAlpha))
{
PdfWriter::CImageDict* pPdfImage = m_pDocument->GetImage(wsImagePathSrc, nAlpha);
@ -2653,6 +2622,8 @@ HRESULT CPdfWriter::AddMetaData(const std::wstring& sMetaName, BYTE* pMetaData,
HRESULT CPdfWriter::AddRedact(const std::vector<double>& arrRedact)
{
m_arrRedact.clear();
if (arrRedact.empty())
return S_OK;
m_arrRedact = arrRedact;
PdfWriter::CArrayObject* pPageBox = (PdfWriter::CArrayObject*)m_pPage->Get("CropBox");
@ -2705,26 +2676,9 @@ HRESULT CPdfWriter::DrawImage1bpp(NSImages::CPixJbig2* pImageBuffer, const unsig
{
m_oCommandManager.Flush();
if (!IsPageValid() || !pImageBuffer)
if (!IsPageValid() || !pImageBuffer || SkipRedact(dX, dY, dW, dH))
return S_OK;
if (!m_arrRedact.empty())
{
double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY);
m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin);
m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax);
for (int i = 0; i < m_arrRedact.size(); i += 4)
{
double xMin = m_arrRedact[i + 0];
double yMin = m_arrRedact[i + 1];
double xMax = m_arrRedact[i + 2];
double yMax = m_arrRedact[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return S_OK;
}
}
m_pPage->GrSave();
UpdateTransform();
@ -2756,26 +2710,9 @@ HRESULT CPdfWriter::DrawImageWith1bppMask(IGrObject* pImage, NSImages::CPixJbig2
{
m_oCommandManager.Flush();
if (!IsPageValid() || !pMaskBuffer || !pImage)
if (!IsPageValid() || !pMaskBuffer || !pImage || SkipRedact(dX, dY, dW, dH))
return S_OK;
if (!m_arrRedact.empty())
{
double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY);
m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin);
m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax);
for (int i = 0; i < m_arrRedact.size(); i += 4)
{
double xMin = m_arrRedact[i + 0];
double yMin = m_arrRedact[i + 1];
double xMax = m_arrRedact[i + 2];
double yMax = m_arrRedact[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return S_OK;
}
}
PdfWriter::CImageDict* pPdfImage = LoadImage((Aggplus::CImage*)pImage, 255);
if (!pPdfImage)
return S_OK;
@ -3224,6 +3161,25 @@ void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, cons
//----------------------------------------------------------------------------------------
// Внутренние функции
//----------------------------------------------------------------------------------------
bool CPdfWriter::SkipRedact(const double& dX, const double& dY, const double& dW, const double& dH)
{
if (m_arrRedact.empty())
return false;
double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY);
m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin);
m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax);
for (int i = 0; i < m_arrRedact.size(); i += 4)
{
double xMin = m_arrRedact[i + 0];
double yMin = m_arrRedact[i + 1];
double xMax = m_arrRedact[i + 2];
double yMax = m_arrRedact[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return true;
}
return false;
}
PdfWriter::CImageDict* CPdfWriter::LoadImage(Aggplus::CImage* pImage, BYTE nAlpha)
{
TColor oColor;

View File

@ -229,6 +229,7 @@ public:
void SetSplit(bool bSplit) { m_bSplit = bSplit; }
private:
bool SkipRedact(const double& dX, const double& dY, const double& dW, const double& dH);
PdfWriter::CImageDict* LoadImage(Aggplus::CImage* pImage, BYTE nAlpha);
PdfWriter::CImageDict* DrawImage(Aggplus::CImage* pImage, const double& dX, const double& dY, const double& dW, const double& dH, const BYTE& nAlpha);
bool DrawText(unsigned char* pCodes, const unsigned int& unLen, const double& dX, const double& dY, const std::string& sPUA);

View File

@ -788,7 +788,7 @@ bool SkipPath(const std::vector<CSegment>& arrForStroke, const CPoint& P1, const
double check2 = A * P2.x + B * P2.y + C;
// Если обе проверки близки к нулю (в пределах эпсилон), то лежит
if ((std::abs(check1) < 0.004) && (std::abs(check2) < 0.004))
if ((std::abs(check1) < 0.006) && (std::abs(check2) < 0.006))
return true;
}
return false;
@ -809,17 +809,10 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
CMatrix oMatrix(m_arrMatrix[0], m_arrMatrix[1], m_arrMatrix[2], m_arrMatrix[3], m_arrMatrix[4], m_arrMatrix[5]);
CMatrix oInverse = oMatrix.Inverse();
std::vector<CSegment> arrForStroke;
Aggplus::CGraphicsPath oPath, oPathRedact, oPathResult;
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
oPathRedact.StartFigure();
oPathRedact.MoveTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]);
oPathRedact.LineTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]);
oPathRedact.LineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]);
oPathRedact.LineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]);
oPathRedact.CloseFigure();
}
if (bEoFill)
oPath.SetRuler(true);
for (int nSubPathIndex = 0, nSubPathCount = pPath->getNumSubpaths(); nSubPathIndex < nSubPathCount; ++nSubPathIndex)
{
GfxSubpath* pSubpath = pPath->getSubpath(nSubPathIndex);
@ -829,6 +822,7 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
double dX = pSubpath->getX(0), dY = pSubpath->getY(0);
oMatrix.Apply(dX, dY);
double dXStart = dX, dYStart = dY, dXCur = dX, dYCur = dY;
oPath.MoveTo(dX, dY);
int nCurPointIndex = 1;
@ -845,6 +839,7 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
double dX3 = pSubpath->getX(nCurPointIndex + 2);
double dY3 = pSubpath->getY(nCurPointIndex + 2);
oMatrix.Apply(dX3, dY3);
dXCur = dX3; dYCur = dY3;
oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
nCurPointIndex += 3;
}
@ -853,12 +848,15 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
dX = pSubpath->getX(nCurPointIndex);
dY = pSubpath->getY(nCurPointIndex);
oMatrix.Apply(dX, dY);
dXCur = dX; dYCur = dY;
oPath.LineTo(dX, dY);
++nCurPointIndex;
}
}
if (pSubpath->isClosed())
oPath.CloseFigure();
else if (bStroke && (std::abs(dXCur - dXStart) > EPS || std::abs(dYCur - dYStart) > EPS))
arrForStroke.push_back(CSegment(CPoint(dXCur, dYCur), CPoint(dXStart, dYStart)));
}
//size_t length1 = oPath.GetPointCount(), compound1 = oPath.GetCloseCount();
@ -870,7 +868,29 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
//}
//std::cout <<std::endl;
oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction);
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
oPathRedact.StartFigure();
oPathRedact.MoveTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]);
oPathRedact.LineTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]);
oPathRedact.LineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]);
oPathRedact.LineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]);
oPathRedact.CloseFigure();
if (bStroke)
{
arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]), CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3])));
arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]), CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3])));
arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]), CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1])));
arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]), CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1])));
}
oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction);
oPath.Reset();
oPathRedact.Reset();
oPath = oPathResult;
}
//oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction);
size_t length = oPathResult.GetPointCount(), compound = oPathResult.GetCloseCount();
std::vector<Aggplus::PointD> points = oPathResult.GetPoints(0, length + compound);
@ -883,6 +903,8 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
m_pRenderer->m_oPath.Clear();
double dXStart = -1, dYStart = -1, dXCur = -1, dYCur = -1;
bool bBreak = false;
for (size_t i = 0; i < length + compound; i++)
{
if (oPathResult.IsCurvePoint(i))
@ -895,6 +917,14 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
oInverse.Apply(dX2, dY2);
double dX3 = points[i + 2].X;
double dY3 = points[i + 2].Y;
if (bBreak)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur = dX3; dYCur = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
@ -903,22 +933,63 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
else if (oPathResult.IsMovePoint(i))
{
double dX = points[i].X, dY = points[i].Y;
oInverse.Apply(dX, dY);
m_pRenderer->m_oPath.MoveTo(dX, dY);
dXStart = dX; dYStart = dY; dXCur = dX; dYCur = dY;
if (bStroke)
bBreak = true;
else
{
oInverse.Apply(dX, dY);
m_pRenderer->m_oPath.MoveTo(dX, dY);
}
}
else if (oPathResult.IsLinePoint(i))
{
double dX = points[i].X, dY = points[i].Y;
if (bStroke && SkipPath(arrForStroke, CPoint(dXCur, dYCur), CPoint(dX, dY)))
{
dXCur = dX; dYCur = dY;
bBreak = true;
continue;
}
if (bBreak)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur = dX; dYCur = dY;
oInverse.Apply(dX, dY);
m_pRenderer->m_oPath.LineTo(dX, dY);
}
else if (oPathResult.IsClosePoint(i))
m_pRenderer->m_oPath.Close();
{
if (bStroke && (std::abs(dXCur - dXStart) > EPS || std::abs(dYCur - dYStart) > EPS) && SkipPath(arrForStroke, CPoint(dXCur, dYCur), CPoint(dXStart, dYStart)))
{
dXCur = dXStart; dYCur = dYStart;
bBreak = true;
continue;
}
if (bStroke || bBreak)
{
if (std::abs(dXCur - dXStart) > EPS || std::abs(dYCur - dYStart) > EPS)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
oInverse.Apply(dXCI, dYCI);
double dXSI = dXStart, dYSI = dYStart;
oInverse.Apply(dXSI, dYSI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
m_pRenderer->m_oPath.LineTo(dXSI, dYSI);
}
}
else
m_pRenderer->m_oPath.Close();
}
}
return;
std::vector<CSegment> arrForStroke;
pk::SkPath skPath, skPathRedact, skPathRes;
if (bEoFill)
skPath.setFillType(pk::SkPathFillType::kEvenOdd);
@ -985,14 +1056,14 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
pk::Op(skPath, skPathRedact, pk::SkPathOp::kDifference_SkPathOp, &skPathRes);
pk::SkPath::Iter iter(skPathRes, false); // false - не сохранять контуры
pk::SkPath::Iter iter(skPathRes, bStroke); // false - не сохранять контуры
pk::SkPoint pts[4];
pk::SkPath::Verb verb;
m_pRenderer->m_oPath.Clear();
double dXStart = -1, dYStart = -1, dXCur = -1, dYCur = -1;
bool bBreak = false;
double dXStart2 = -1, dYStart2 = -1, dXCur2 = -1, dYCur2 = -1;
bool bBreak2 = false;
while ((verb = iter.next(pts)) != pk::SkPath::kDone_Verb)
{
switch (verb)
@ -1000,9 +1071,9 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
case pk::SkPath::kMove_Verb:
{
double dX = pts[0].x(), dY = pts[0].y();
dXStart = dX; dYStart = dY; dXCur = dX; dYCur = dY;
dXStart2 = dX; dYStart2 = dY; dXCur2 = dX; dYCur2 = dY;
if (bStroke)
bBreak = true;
bBreak2 = true;
else
{
oInverse.Apply(dX, dY);
@ -1013,20 +1084,20 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
case pk::SkPath::kLine_Verb:
{
double dX = pts[1].x(), dY = pts[1].y();
if (bStroke && SkipPath(arrForStroke, CPoint(dXCur, dYCur), CPoint(dX, dY)))
if (bStroke && SkipPath(arrForStroke, CPoint(dXCur2, dYCur2), CPoint(dX, dY)))
{
dXCur = dX; dYCur = dY;
bBreak = true;
dXCur2 = dX; dYCur2 = dY;
bBreak2 = true;
continue;
}
if (bBreak)
if (bBreak2)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur = dX; dYCur = dY;
dXCur2 = dX; dYCur2 = dY;
oInverse.Apply(dX, dY);
m_pRenderer->m_oPath.LineTo(dX, dY);
break;
@ -1054,14 +1125,14 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
oInverse.Apply(dX2, dY2);
double dX3 = cubic[3].x();
double dY3 = cubic[3].y();
if (bBreak)
if (bBreak2)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur = dX3; dYCur = dY3;
dXCur2 = dX3; dYCur2 = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
break;
@ -1076,14 +1147,14 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
oInverse.Apply(dX2, dY2);
double dX3 = pts[3].x();
double dY3 = pts[3].y();
if (bBreak)
if (bBreak2)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur = dX3; dYCur = dY3;
dXCur2 = dX3; dYCur2 = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
break;
@ -1118,14 +1189,14 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
oInverse.Apply(dX2, dY2);
double dX3 = cubic[3].x();
double dY3 = cubic[3].y();
if (bBreak)
if (bBreak2)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur = dX3; dYCur = dY3;
dXCur2 = dX3; dYCur2 = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
}
@ -1133,20 +1204,20 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
}
case pk::SkPath::kClose_Verb:
{
if (bStroke && (std::abs(dXCur - dXStart) > EPS || std::abs(dYCur - dYStart) > EPS) && SkipPath(arrForStroke, CPoint(dXCur, dYCur), CPoint(dXStart, dYStart)))
if (bStroke && (std::abs(dXCur2 - dXStart2) > EPS || std::abs(dYCur2 - dYStart2) > EPS) && SkipPath(arrForStroke, CPoint(dXCur2, dYCur2), CPoint(dXStart2, dYStart2)))
{
dXCur = dXStart; dYCur = dYStart;
bBreak = true;
dXCur2 = dXStart2; dYCur2 = dYStart2;
bBreak2 = true;
continue;
}
if (bStroke || bBreak)
if (bStroke || bBreak2)
{
if (std::abs(dXCur - dXStart) > EPS || std::abs(dYCur - dYStart) > EPS)
if (std::abs(dXCur2 - dXStart2) > EPS || std::abs(dYCur2 - dYStart2) > EPS)
{
bBreak = false;
double dXCI = dXCur, dYCI = dYCur;
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
double dXSI = dXStart, dYSI = dYStart;
double dXSI = dXStart2, dYSI = dYStart2;
oInverse.Apply(dXSI, dYSI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
m_pRenderer->m_oPath.LineTo(dXSI, dYSI);

View File

@ -303,6 +303,16 @@ static inline void UpdateMaxMinPoints(double& dMinX, double& dMinY, double& dMax
if (dY > dMaxY)
dMaxY = dY;
}
void CPath::Redact(const CTransform& oTransform, const std::vector<double>& arrRedact)
{
Aggplus::CGraphicsPath oPath;
for (int nIndex = 0, nCount = m_vCommands.size(); nIndex < nCount; nIndex++)
{
CPathCommandBase* pCommand = m_vCommands.at(nIndex);
// CPath to CGraphicsPath
pCommand->ToCGraphicsPath(oTransform, oPath);
}
}
void CPath::Draw(PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill)
{
for (int nIndex = 0, nCount = m_vCommands.size(); nIndex < nCount; nIndex++)
@ -381,6 +391,12 @@ 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)
{
double dX, dY;
oTransform.Transform(x, y, &dX, &dY);
oPath.MoveTo(dX, dY);
}
void CPath::CPathLineTo::Draw(PdfWriter::CPage* pPage)
{
pPage->LineTo(x, y);
@ -389,6 +405,12 @@ 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)
{
double dX, dY;
oTransform.Transform(x, y, &dX, &dY);
oPath.LineTo(dX, dY);
}
void CPath::CPathCurveTo::Draw(PdfWriter::CPage* pPage)
{
pPage->CurveTo(x1, y1, x2, y2, xe, ye);
@ -399,6 +421,14 @@ 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)
{
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);
oPath.CurveTo(dX1, dY1, dX2, dY2, dX3, dY3);
}
void CPath::CPathArcTo::Draw(PdfWriter::CPage* pPage)
{
if (sweepAngle >= 360 - 0.001)
@ -410,6 +440,10 @@ void CPath::CPathArcTo::UpdateBounds(double& dL, double& dT, double& dR, double&
{
UpdateMaxMinPoints(dL, dT, dR, dB, x, y);
UpdateMaxMinPoints(dL, dT, dR, dB, x + w, y + h);
}
void CPath::CPathArcTo::ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath)
{
}
void CPath::CPathClose::Draw(PdfWriter::CPage* pPage)
{
@ -418,6 +452,10 @@ 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)
{
oPath.CloseFigure();
}
void CPath::CPathText::Draw(PdfWriter::CPage* pPage)
{
// TODO: Если данная команда будет часто вызываться, тогда ее нужно будет оптимизировать, точно также как это делается в обычном тексте
@ -432,6 +470,11 @@ 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)
{
// Весь текст проверяется в CPdfWriter::PathCommandDrawText
// Эта функция не должна быть вызвана
}
void CBrushState::Reset()
{
m_lType = c_BrushTypeSolid;

View File

@ -34,6 +34,7 @@
#include "../../DesktopEditor/common/Types.h"
#include "../../DesktopEditor/graphics/AggPlusEnums.h"
#include "../../DesktopEditor/graphics/GraphicsPath.h"
#include "Types.h"
#include <string>
@ -1261,6 +1262,64 @@ private:
double m_dWordSpace;
double m_dHorizontalScaling;
};
struct CTransform
{
CTransform()
{
Reset();
}
void operator=(const CTransform& oT)
{
m11 = oT.m11;
m12 = oT.m12;
m21 = oT.m21;
m22 = oT.m22;
dx = oT.dx;
dy = oT.dy;
}
void Reset()
{
m11 = 1.0;
m12 = 0.0;
m21 = 0.0;
m22 = 1.0;
dx = 0;
dy = 0;
}
bool IsIdentity() const
{
if (fabs(m11 - 1) < 0.001
&& fabs(m12) < 0.001
&& fabs(m21) < 0.001
&& fabs(m22 - 1) < 0.001
&& fabs(dx) < 0.001
&& fabs(dy) < 0.001)
return true;
return false;
}
void Set(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY)
{
m11 = dM11;
m12 = dM12;
m21 = dM21;
m22 = dM22;
dx = dX;
dy = dY;
}
void Transform(double dUserX, double dUserY, double* pdDeviceX, double* pdDeviceY) const
{
*pdDeviceX = dUserX * m11 + dUserY * m21 + dx;
*pdDeviceY = dUserX * m12 + dUserY * m22 + dy;
}
double m11;
double m12;
double m21;
double m22;
double dx;
double dy;
};
class CPath
{
private:
@ -1291,6 +1350,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;
};
class CPathMoveTo : public CPathCommandBase
{
@ -1311,6 +1371,7 @@ private:
{
return rendererpathcommand_MoveTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
public:
@ -1336,6 +1397,7 @@ private:
{
return rendererpathcommand_LineTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
public:
@ -1365,6 +1427,7 @@ private:
{
return rendererpathcommand_CurveTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
public:
@ -1399,6 +1462,7 @@ private:
{
return rendererpathcommand_ArcTo;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
public:
@ -1427,6 +1491,7 @@ private:
{
return rendererpathcommand_Close;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
};
class CPathText : public CPathCommandBase
{
@ -1456,6 +1521,7 @@ private:
{
return rendererpathcommand_Text;
}
void ToCGraphicsPath(const CTransform& oTransform, Aggplus::CGraphicsPath& oPath);
public:
@ -1531,6 +1597,7 @@ 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);
private:
@ -1550,64 +1617,7 @@ public:
std::vector<CPathCommandBase*> m_vCommands;
bool m_bIsMoveTo;
};
struct CTransform
{
CTransform()
{
Reset();
}
void operator=(const CTransform& oT)
{
m11 = oT.m11;
m12 = oT.m12;
m21 = oT.m21;
m22 = oT.m22;
dx = oT.dx;
dy = oT.dy;
}
void Reset()
{
m11 = 1.0;
m12 = 0.0;
m21 = 0.0;
m22 = 1.0;
dx = 0;
dy = 0;
}
bool IsIdentity() const
{
if (fabs(m11 - 1) < 0.001
&& fabs(m12) < 0.001
&& fabs(m21) < 0.001
&& fabs(m22 - 1) < 0.001
&& fabs(dx) < 0.001
&& fabs(dy) < 0.001)
return true;
return false;
}
void Set(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY)
{
m11 = dM11;
m12 = dM12;
m21 = dM21;
m22 = dM22;
dx = dX;
dy = dY;
}
void Transform(double dUserX, double dUserY, double* pdDeviceX, double* pdDeviceY)
{
*pdDeviceX = dUserX * m11 + dUserY * m21 + dx;
*pdDeviceY = dUserX * m12 + dUserY * m22 + dy;
}
double m11;
double m12;
double m21;
double m22;
double dx;
double dy;
};
class CCommandManager
{
public: