Merge pull request 'Fix build' (#457) from fix/pdf-redact into release/v9.1.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/457
This commit is contained in:
Oleg Korshul
2025-10-01 08:01:51 +00:00
6 changed files with 9 additions and 286 deletions

View File

@ -3298,7 +3298,7 @@ bool CPdfEditor::EditWidgets(IAdvancedCommand* pCommand)
if (m_nMode == Mode::Unknown && !IncrementalUpdates())
return false;
//WriteRedact({});
WriteRedact({});
m_pWriter->AddRedact({});
m_arrRedact.clear();

View File

@ -38,7 +38,6 @@ INCLUDEPATH += \
lib/goo \
lib/fofi \
lib/splash \
lib/pathkit \
lib
HEADERS += $$files(lib/*.h, true)

View File

@ -188,7 +188,7 @@ void GlobalParamsAdaptor::AddRedact(const std::vector<double>& arrRedactBox)
}
bool GlobalParamsAdaptor::InRedact(double dX, double dY)
{
for (int i = 0; i < m_arrRedactBox.size(); i += 8)
for (int i = 0; i < m_arrRedactBox.size(); i += 4)
{
double xMin = m_arrRedactBox[i + 0];
double yMin = m_arrRedactBox[i + 1];

View File

@ -2381,7 +2381,12 @@ namespace PdfReader
return;
}
if (((GlobalParamsAdaptor*)globalParams)->InRedact(dX + dDx / 2.0, dY))
double startX, startY, endX, endY;
Transform(pGState->getCTM(), dX, dY, &startX, &startY);
Transform(pGState->getCTM(), dX + dDx, dY + dDy, &endX, &endY);
double dCenterX = (startX + endX) / 2;
double dCenterY = (startY + endY) / 2;
if (((GlobalParamsAdaptor*)globalParams)->InRedact(dCenterX, dCenterY))
return;
double* pCTM = pGState->getCTM();

View File

@ -36,8 +36,6 @@
#include "../lib/xpdf/GfxFont.h"
#include "../lib/xpdf/XRef.h"
// Skia PathOps #include "../lib/pathkit/include/core/SkPath.h"
// Skia PathOps #include "../lib/pathkit/include/pathops/SkPathOps.h"
#include "../../DesktopEditor/graphics/GraphicsPath.h"
@ -777,40 +775,6 @@ void RedactOutputDev::clearSoftMask(GfxState *pGState)
}
/* Skia PathOps
// Конвертирует conic в массив квадратичных Безье (минимум 1 сегмент)
void ConvertConicToQuads(const pk::SkPoint& p0, const pk::SkPoint& p1, const pk::SkPoint& p2, pk::SkScalar w, pk::SkPoint pts[], int pow2) {
const pk::SkScalar k = 0.5f; // Фактор дробления (можно адаптировать)
pk::SkPoint q0 = p0;
pk::SkPoint q2 = p2;
pk::SkPoint q1 = pk::SkPoint::Make(
(p0.x() + w * p1.x() + p2.x()) / (2 + w),
(p0.y() + w * p1.y() + p2.y()) / (2 + w)
);
if (pow2 == 1) {
pts[0] = q0;
pts[1] = q1;
pts[2] = q2;
return;
}
// Рекурсивное дробление
pk::SkPoint left[3], right[3];
pk::SkPoint mid = pk::SkPoint::Make(
(q0.x() + q2.x() + 2 * w * q1.x()) / (2 + 2 * w),
(q0.y() + q2.y() + 2 * w * q1.y()) / (2 + 2 * w)
);
ConvertConicToQuads(q0, q1, mid, w, left, pow2 - 1);
ConvertConicToQuads(mid, q1, q2, w, right, pow2 - 1);
// Слияние результатов
std::copy(left, left + 3, pts);
std::copy(right + 1, right + 3, pts + 3);
}
*/
bool SkipPath(const std::vector<CSegment>& arrForStroke, const CPoint& P1, const CPoint& P2)
{
for (int i = 0; i < arrForStroke.size(); ++i)
@ -1085,252 +1049,6 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC
oPathResult = Aggplus::CalcBooleanOperation(oPath, m_oPathRedact, Aggplus::BooleanOpType::Subtraction);
DrawPathRedact(&oPathResult, bStroke);
}
return;
/* Skia PathOps
pk::SkPath skPath, skPathRedact, skPathRes;
if (bEoFill)
skPath.setFillType(pk::SkPathFillType::kEvenOdd);
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
skPathRedact.moveTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]);
skPathRedact.lineTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]);
skPathRedact.lineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]);
skPathRedact.lineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]);
skPathRedact.close();
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])));
}
}
for (int nSubPathIndex = 0, nSubPathCount = pPath->getNumSubpaths(); nSubPathIndex < nSubPathCount; ++nSubPathIndex)
{
GfxSubpath* pSubpath = pPath->getSubpath(nSubPathIndex);
int nPointsCount = pSubpath->getNumPoints();
double dX = pSubpath->getX(0), dY = pSubpath->getY(0);
oMatrix.Apply(dX, dY);
double dXStart = dX, dYStart = dY, dXCur = dX, dYCur = dY;
skPath.moveTo(dX, dY);
int nCurPointIndex = 1;
while (nCurPointIndex < nPointsCount)
{
if (pSubpath->getCurve(nCurPointIndex))
{
dX = pSubpath->getX(nCurPointIndex);
dY = pSubpath->getY(nCurPointIndex);
oMatrix.Apply(dX, dY);
double dX2 = pSubpath->getX(nCurPointIndex + 1);
double dY2 = pSubpath->getY(nCurPointIndex + 1);
oMatrix.Apply(dX2, dY2);
double dX3 = pSubpath->getX(nCurPointIndex + 2);
double dY3 = pSubpath->getY(nCurPointIndex + 2);
oMatrix.Apply(dX3, dY3);
dXCur = dX3; dYCur = dY3;
skPath.cubicTo(dX, dY, dX2, dY2, dX3, dY3);
nCurPointIndex += 3;
}
else
{
dX = pSubpath->getX(nCurPointIndex);
dY = pSubpath->getY(nCurPointIndex);
oMatrix.Apply(dX, dY);
dXCur = dX, dYCur = dY;
skPath.lineTo(dX, dY);
++nCurPointIndex;
}
}
if (pSubpath->isClosed())
skPath.close();
else if (bStroke && (std::abs(dXCur - dXStart) > EPS || std::abs(dYCur - dYStart) > EPS))
arrForStroke.push_back(CSegment(CPoint(dXCur, dYCur), CPoint(dXStart, dYStart)));
}
pk::Op(skPath, skPathRedact, pk::SkPathOp::kDifference_SkPathOp, &skPathRes);
pk::SkPath::Iter iter(skPathRes, bStroke); // false - не сохранять контуры
pk::SkPoint pts[4];
pk::SkPath::Verb verb;
m_pRenderer->m_oPath.Clear();
double dXStart2 = -1, dYStart2 = -1, dXCur2 = -1, dYCur2 = -1;
bool bBreak2 = false;
while ((verb = iter.next(pts)) != pk::SkPath::kDone_Verb)
{
switch (verb)
{
case pk::SkPath::kMove_Verb:
{
double dX = pts[0].x(), dY = pts[0].y();
dXStart2 = dX; dYStart2 = dY; dXCur2 = dX; dYCur2 = dY;
if (bStroke)
bBreak2 = true;
else
{
oInverse.Apply(dX, dY);
m_pRenderer->m_oPath.MoveTo(dX, dY);
}
break;
}
case pk::SkPath::kLine_Verb:
{
double dX = pts[1].x(), dY = pts[1].y();
if (bStroke && SkipPath(arrForStroke, CPoint(dXCur2, dYCur2), CPoint(dX, dY)))
{
dXCur2 = dX; dYCur2 = dY;
bBreak2 = true;
continue;
}
if (bBreak2)
{
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur2 = dX; dYCur2 = dY;
oInverse.Apply(dX, dY);
m_pRenderer->m_oPath.LineTo(dX, dY);
break;
}
case pk::SkPath::kQuad_Verb:
{
// Конвертация квадратичной в кубическую кривую
pk::SkPoint cubic[4];
cubic[0] = pts[0]; // Начальная точка
cubic[1] = {
(2.0f * pts[1].x() + pts[0].x()) / 3.0f,
(2.0f * pts[1].y() + pts[0].y()) / 3.0f
}; // Первая контрольная точка
cubic[2] = {
(2.0f * pts[1].x() + pts[2].x()) / 3.0f,
(2.0f * pts[1].y() + pts[2].y()) / 3.0f
}; // Вторая контрольная точка
cubic[3] = pts[2]; // Конечная точка
double dX = cubic[1].x();
double dY = cubic[1].y();
oInverse.Apply(dX, dY);
double dX2 = cubic[2].x();
double dY2 = cubic[2].y();
oInverse.Apply(dX2, dY2);
double dX3 = cubic[3].x();
double dY3 = cubic[3].y();
if (bBreak2)
{
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur2 = dX3; dYCur2 = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
break;
}
case pk::SkPath::kCubic_Verb:
{
double dX = pts[1].x();
double dY = pts[1].y();
oInverse.Apply(dX, dY);
double dX2 = pts[2].x();
double dY2 = pts[2].y();
oInverse.Apply(dX2, dY2);
double dX3 = pts[3].x();
double dY3 = pts[3].y();
if (bBreak2)
{
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur2 = dX3; dYCur2 = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
break;
}
case pk::SkPath::kConic_Verb:
{
const int pow2 = 1; // Кол-во сегментов (2^pow2). Для PDF обычно хватает 1.
pk::SkPoint quadPts[1 + 2 * (1 << pow2)]; // Массив для квадратичных кривых
ConvertConicToQuads(pts[0], pts[1], pts[2], iter.conicWeight(), quadPts, pow2);
// Добавляем каждую квадратичную кривую как отдельный сегмент
for (int i = 0; i < (1 << pow2); ++i)
{
// Конвертация квадратичной в кубическую кривую
pk::SkPoint cubic[4];
cubic[0] = quadPts[0 + 2*i]; // Начальная точка
cubic[1] = {
quadPts[0 + 2*i].x() + (2.0f/3.0f) * (quadPts[1 + 2*i].x() - quadPts[0 + 2*i].x()),
quadPts[0 + 2*i].y() + (2.0f/3.0f) * (quadPts[1 + 2*i].y() - quadPts[0 + 2*i].y())
}; // Первая контрольная точка
cubic[2] = {
quadPts[1 + 2*i].x() + (2.0f/3.0f) * (quadPts[2 + 2*i].x() - quadPts[1 + 2*i].x()),
quadPts[1 + 2*i].y() + (2.0f/3.0f) * (quadPts[2 + 2*i].y() - quadPts[1 + 2*i].y())
}; // Вторая контрольная точка
cubic[3] = quadPts[2 + 2*i]; // Конечная точка
double dX = cubic[1].x();
double dY = cubic[1].y();
oInverse.Apply(dX, dY);
double dX2 = cubic[2].x();
double dY2 = cubic[2].y();
oInverse.Apply(dX2, dY2);
double dX3 = cubic[3].x();
double dY3 = cubic[3].y();
if (bBreak2)
{
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
}
dXCur2 = dX3; dYCur2 = dY3;
oInverse.Apply(dX3, dY3);
m_pRenderer->m_oPath.CurveTo(dX, dY, dX2, dY2, dX3, dY3);
}
break;
}
case pk::SkPath::kClose_Verb:
{
if (bStroke && (std::abs(dXCur2 - dXStart2) > EPS || std::abs(dYCur2 - dYStart2) > EPS) && SkipPath(arrForStroke, CPoint(dXCur2, dYCur2), CPoint(dXStart2, dYStart2)))
{
dXCur2 = dXStart2; dYCur2 = dYStart2;
bBreak2 = true;
continue;
}
if (bStroke || bBreak2)
{
if (std::abs(dXCur2 - dXStart2) > EPS || std::abs(dYCur2 - dYStart2) > EPS)
{
bBreak2 = false;
double dXCI = dXCur2, dYCI = dYCur2;
oInverse.Apply(dXCI, dYCI);
double dXSI = dXStart2, dYSI = dYStart2;
oInverse.Apply(dXSI, dYSI);
m_pRenderer->m_oPath.MoveTo(dXCI, dYCI);
m_pRenderer->m_oPath.LineTo(dXSI, dYSI);
}
}
else
m_pRenderer->m_oPath.Close();
break;
}
case pk::SkPath::kDone_Verb:
break;
}
}
*/
}
void RedactOutputDev::DoPath(GfxState* pGState, GfxPath* pPath, double* pCTM)
{

View File

@ -47,6 +47,7 @@
#include <algorithm>
#include <math.h>
#include <vector>
#include <cmath>
#ifdef __linux__
#include <string.h>