Redact Do&Undo

This commit is contained in:
Svetlana Kulikova
2025-08-20 14:54:02 +03:00
parent 2a6c50db89
commit d092b88d9b
21 changed files with 208 additions and 41 deletions

View File

@ -327,6 +327,12 @@ public:
}
return false;
}
bool UndoRedact()
{
if (m_nType == 0)
return ((CPdfFile*)m_pFile)->UndoRedact();
return false;
}
BYTE* GetGlyphs(int nPageIndex)
{

View File

@ -207,6 +207,40 @@ JSSmart<CJSValue> CDrawingFileEmbed::UnmergePages()
return CJSContext::createBool(m_pFile->UnmergePages());
return CJSContext::createBool(false);
}
JSSmart<CJSValue> CDrawingFileEmbed::RedactPage(JSSmart<CJSValue> nPageIndex, JSSmart<CJSValue> arrRedactBox, JSSmart<CJSValue> dataFiller)
{
bool result = false;
if (m_pFile)
{
int pageIndex = nPageIndex->toInt32();
JSSmart<CJSArray> arrBox = arrRedactBox->toArray();
int nCountBox = arrBox->getCount();
double* pBox = NULL;
if (0 < nCountBox)
pBox = new double[nCountBox];
for (int i = 0; i < nCountBox; i++)
pBox[i] = arrBox->get(i)->toDouble();
JSSmart<CJSTypedArray> dataPtr = dataFiller->toTypedArray();
CJSDataBuffer buffer = dataPtr->getData();
result = m_pFile->RedactPage(pageIndex, pBox, nCountBox / 4, buffer.Data, (int)buffer.Len);
if (pBox)
delete[] pBox;
if (buffer.IsExternalize)
buffer.Free();
}
return CJSContext::createBool(result);
}
JSSmart<CJSValue> CDrawingFileEmbed::UndoRedact()
{
if (m_pFile)
return CJSContext::createBool(m_pFile->UndoRedact());
return CJSContext::createBool(false);
}
bool EmbedDrawingFile(JSSmart<NSJSBase::CJSContext>& context, IOfficeDrawingFile* pFile)
{

View File

@ -54,6 +54,8 @@ public:
JSSmart<CJSValue> SplitPages(JSSmart<CJSValue> arrPageIndexes, JSSmart<CJSValue> data);
JSSmart<CJSValue> MergePages(JSSmart<CJSValue> data, JSSmart<CJSValue> nMaxID, JSSmart<CJSValue> sPrefixForm);
JSSmart<CJSValue> UnmergePages();
JSSmart<CJSValue> RedactPage(JSSmart<CJSValue> nPageIndex, JSSmart<CJSValue> arrRedactBox, JSSmart<CJSValue> dataFiller);
JSSmart<CJSValue> UndoRedact();
DECLARE_EMBED_METHODS
};

View File

@ -33,6 +33,8 @@ namespace NSDrawingFileEmbed
FUNCTION_WRAPPER_V8_2(_SplitPages, SplitPages)
FUNCTION_WRAPPER_V8_3(_MergePages, MergePages)
FUNCTION_WRAPPER_V8_0(_UnmergePages, UnmergePages)
FUNCTION_WRAPPER_V8_3(_RedactPage, RedactPage)
FUNCTION_WRAPPER_V8_0(_UndoRedact, UndoRedact)
v8::Handle<v8::ObjectTemplate> CreateTemplate(v8::Isolate* isolate)
{
@ -65,6 +67,8 @@ namespace NSDrawingFileEmbed
NSV8Objects::Template_Set(result, "SplitPages", _SplitPages);
NSV8Objects::Template_Set(result, "MergePages", _MergePages);
NSV8Objects::Template_Set(result, "UnmergePages", _UnmergePages);
NSV8Objects::Template_Set(result, "RedactPage", _RedactPage);
NSV8Objects::Template_Set(result, "UndoRedact", _UndoRedact);
return handle_scope.Escape(result);
}

View File

@ -1225,6 +1225,7 @@ bool CWidgetsInfo::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafil
CRedact::CRedact() : IAdvancedCommand(AdvancedCommandType::Redact) {}
CRedact::~CRedact() {}
int CRedact::GetFlag() const { return m_nFlag; }
void CRedact::GetBounds(double& dX1, double& dY1, double& dX2, double& dY2)
{
dX1 = m_dX1;
@ -1233,13 +1234,18 @@ void CRedact::GetBounds(double& dX1, double& dY1, double& dX2, double& dY2)
dY2 = m_dY2;
}
const std::vector<double>& CRedact::GetQuadPoints() { return m_arrQuadPoints; }
BYTE* CRedact::GetRender(LONG& nLen)
{
nLen = m_nRenderLen;
return m_pRender;
}
bool CRedact::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRenderter* pCorrector)
{
int n = pReader->ReadInt();
m_arrQuadPoints.reserve(n);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < 8; ++j)
for (int j = 0; j < 4; ++j)
m_arrQuadPoints.push_back(pReader->ReadDouble());
}

View File

@ -54,6 +54,8 @@
"_SplitPages",
"_MergePages",
"_UnmergePages",
"_RedactPage",
"_UndoRedact",
"_GetImageBase64",
"_GetImageBase64Len",
"_GetImageBase64Ptr",

View File

@ -701,8 +701,7 @@ HEADERS += \
$$PDF_ROOT_DIR/SrcWriter/Utils.h \
$$PDF_ROOT_DIR/SrcWriter/Metadata.h \
$$PDF_ROOT_DIR/SrcWriter/ICCProfile.h \
$$PDF_ROOT_DIR/SrcWriter/States.h \
$$PDF_ROOT_DIR/SrcWriter/RedactOutputDev.h
$$PDF_ROOT_DIR/SrcWriter/States.h
SOURCES += \
$$PDF_ROOT_DIR/SrcWriter/AcroForm.cpp \
@ -731,8 +730,7 @@ SOURCES += \
$$PDF_ROOT_DIR/SrcWriter/Streams.cpp \
$$PDF_ROOT_DIR/SrcWriter/Utils.cpp \
$$PDF_ROOT_DIR/SrcWriter/Metadata.cpp \
$$PDF_ROOT_DIR/SrcWriter/States.cpp \
$$PDF_ROOT_DIR/SrcWriter/RedactOutputDev.cpp
$$PDF_ROOT_DIR/SrcWriter/States.cpp
# PdfFile

View File

@ -160,6 +160,14 @@ CFile.prototype["UndoMergePages"] = function()
{
return this._UndoMergePages();
};
CFile.prototype["RedactPage"] = function(pageIndex, arrRedactBox, arrayBufferChanges)
{
return this._RedactPage(pageIndex, arrRedactBox, arrayBufferChanges);
};
CFile.prototype["UndoRedact"] = function()
{
return this._UndoRedact();
};
// INFO DOCUMENT
CFile.prototype.getInfo = function()

View File

@ -135,6 +135,17 @@ CFile.prototype._UndoMergePages = function()
return g_native_drawing_file["UnmergePages"]();
};
CFile.prototype._RedactPage = function(pageIndex, box, filler)
{
let dataFiller = (undefined !== filler.byteLength) ? new Float64Array(filler) : filler;
return g_native_drawing_file["RedactPage"](pageIndex, box, dataFiller);
};
CFile.prototype._UndoRedact = function()
{
return g_native_drawing_file["UndoRedact"]();
};
// FONTS
CFile.prototype._isNeedCMap = function()
{

View File

@ -192,6 +192,38 @@ CFile.prototype._UndoMergePages = function()
return Module["_UnmergePages"](this.nativeFile) == 1;
};
CFile.prototype._RedactPage = function(pageIndex, arrRedactBox, arrayBufferChanges)
{
let changesPtr = 0;
let changesLen = 0;
if (arrayBufferChanges)
{
let changes = new Uint8Array(arrayBufferChanges);
changesLen = changes.length;
changesPtr = Module["_malloc"](changesLen);
Module["HEAP8"].set(changes, changesPtr);
}
let memoryBuffer = new Int32Array(arrRedactBox.length);
for (let i = 0; i < arrRedactBox.length; i++)
memoryBuffer[i] = Math.round(arrRedactBox[i] * 10000);
let pointer = Module["_malloc"](memoryBuffer.length * 4);
Module["HEAP32"].set(memoryBuffer, pointer >> 2);
let bRes = Module["_RedactPage"](this.nativeFile, pageIndex, pointer, memoryBuffer.length / 4, changesPtr, changesLen);
changesPtr = 0; // Success or not, changesPtr is either taken or freed
Module["_free"](pointer);
return bRes == 1;
};
CFile.prototype._UndoRedact = function()
{
return Module["_UndoRedact"](this.nativeFile) == 1;
};
// FONTS
CFile.prototype._isNeedCMap = function()
{

View File

@ -178,9 +178,18 @@ WASM_EXPORT int UnmergePages(CDrawingFile* pFile)
{
return pFile->UnmergePages() ? 1 : 0;
}
WASM_EXPORT int RedactPage(CDrawingFile* pFile, int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* data, int size)
WASM_EXPORT int RedactPage(CDrawingFile* pFile, int nPageIndex, int* arrRedactBox, int nLengthX4, BYTE* data, int size)
{
return pFile->RedactPage(nPageIndex, arrRedactBox, nLengthX4, data, size) ? 1 : 0;
double* arrDRedactBox = new double[nLengthX4 * 4];
for (int i = 0; i < nLengthX4 * 4; ++i)
arrDRedactBox[i] = arrRedactBox[i] / 10000.0;
int nRes = pFile->RedactPage(nPageIndex, arrDRedactBox, nLengthX4, data, size) ? 1 : 0;
delete[] arrDRedactBox;
return nRes;
}
WASM_EXPORT int UndoRedact(CDrawingFile* pFile)
{
return pFile->UndoRedact() ? 1 : 0;
}
WASM_EXPORT void* GetImageBase64(CDrawingFile* pFile, int rId)

View File

@ -32,6 +32,7 @@
#include "PdfEditor.h"
#include "../DesktopEditor/common/Path.h"
#include "../DesktopEditor/graphics/commands/AnnotField.h"
#include "SrcReader/Adaptors.h"
#include "SrcReader/PdfAnnot.h"
@ -50,8 +51,10 @@
#include "SrcWriter/Streams.h"
#include "SrcWriter/Destination.h"
#include "SrcWriter/Outline.h"
#include "SrcWriter/RedactOutputDev.h"
#include "SrcWriter/GState.h"
#ifndef BUILDING_WASM_MODULE
#include "SrcWriter/RedactOutputDev.h"
#endif
#define AddToObject(oVal)\
{\
@ -3523,29 +3526,11 @@ bool CPdfEditor::IsBase14(const std::wstring& wsFontName, bool& bBold, bool& bIt
return true;
return false;
}
void CPdfEditor::Redact(CRedact* pCommand)
void CPdfEditor::Redact(IAdvancedCommand* _pCommand)
{
CRedact* pCommand = (CRedact*)_pCommand;
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
int nOriginIndex = m_nEditPage;
if (m_nMode == Mode::WriteNew)
{
PdfWriter::CPageTree* pPageTree = pDoc->GetPageTree();
PdfWriter::CObjectBase* pObj = pPageTree->GetObj(m_nEditPage);
PdfWriter::CFakePage* pFakePage = NULL;
if (pObj)
pFakePage = dynamic_cast<PdfWriter::CFakePage*>(pObj);
if (pFakePage)
nOriginIndex = pFakePage->GetOriginIndex();
}
PDFDoc* pPDFDocument = NULL;
int nPageIndex = m_pReader->GetPageIndex(nOriginIndex, &pPDFDocument);
if (nPageIndex < 0 || !pPDFDocument)
return;
PdfWriter::RedactOutputDev oRedactOut(m_pWriter);
oRedactOut.NewPDF(pPDFDocument->getXRef());
oRedactOut.SetRedact(pCommand->GetQuadPoints());
pPDFDocument->displayPage(&oRedactOut, nPageIndex, 72.0, 72.0, 0, gTrue, gFalse, gFalse);
Redact(pCommand->GetQuadPoints());
int nFlags = pCommand->GetFlag();
if (nFlags & (1 << 0))
@ -3592,8 +3577,10 @@ void CPdfEditor::Redact(const std::vector<double>& arrQuadPoints)
if (nPageIndex < 0 || !pPDFDocument)
return;
#ifndef BUILDING_WASM_MODULE
PdfWriter::RedactOutputDev oRedactOut(m_pWriter);
oRedactOut.NewPDF(pPDFDocument->getXRef());
oRedactOut.SetRedact(arrQuadPoints);
pPDFDocument->displayPage(&oRedactOut, nPageIndex, 72.0, 72.0, 0, gTrue, gFalse, gFalse);
#endif
}

View File

@ -100,7 +100,7 @@ public:
void AddShapeXML(const std::string& sXML);
void EndMarkedContent();
bool IsBase14(const std::wstring& wsFontName, bool& bBold, bool& bItalic, std::wstring& wsFontPath);
void Redact(CRedact* pCommand);
void Redact(IAdvancedCommand* pCommand);
void Redact(const std::vector<double>& arrQuadPoints);
bool SplitPages(const int* arrPageIndex, unsigned int unLength);

View File

@ -363,6 +363,12 @@ bool CPdfFile::RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, B
}
return m_pInternal->pReader->RedactPage(nPageIndex, arrRedactBox, nLengthX4, pChanges, nLength);
}
bool CPdfFile::UndoRedact()
{
if (!m_pInternal->pReader)
return false;
return m_pInternal->pReader->UndoRedact();
}
int CPdfFile::GetRotate(int nPageIndex)
{
if (!m_pInternal->pReader)

View File

@ -131,6 +131,7 @@ public:
bool MergePages(BYTE* data, DWORD length, int nMaxID = 0, const std::string& sPrefixForm = "");
bool UnmergePages();
bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* pChanges = NULL, int nLength = 0);
bool UndoRedact();
int GetRotate(int nPageIndex);
int GetMaxRefID();
BYTE* GetWidgets();

View File

@ -38,6 +38,7 @@
#include "../DesktopEditor/common/Directory.h"
#include "../DesktopEditor/common/StringExt.h"
#include "../DesktopEditor/graphics/pro/js/wasm/src/serialize.h"
#include "../DesktopEditor/graphics/MetafileToRenderer.h"
#include "SrcReader/Adaptors.h"
#include "SrcReader/PdfAnnot.h"
@ -777,6 +778,15 @@ bool CPdfReader::RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4,
return true;
}
bool CPdfReader::UndoRedact()
{
if (m_vRedact.empty())
return false;
CPdfRedact* pRedact = m_vRedact.back();
delete pRedact;
m_vRedact.pop_back();
return true;
}
void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* pbBreak)
{
PDFDoc* pDoc = NULL;
@ -785,6 +795,12 @@ void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool*
if (nPageIndex < 0 || !pDoc || !pFontList)
return;
for (int i = 0 ; i < m_vRedact.size(); ++i)
{
if (m_vRedact[i]->m_nPageIndex == _nPageIndex)
((GlobalParamsAdaptor*)globalParams)->AddRedact(m_vRedact[i]->m_arrRedactBox);
}
PdfReader::RendererOutputDev oRendererOut(pRenderer, m_pFontManager, pFontList);
oRendererOut.NewPDF(pDoc->getXRef());
oRendererOut.SetBreak(pbBreak);
@ -793,6 +809,18 @@ void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool*
nRotate = -pDoc->getPageRotate(nPageIndex);
#endif
pDoc->displayPage(&oRendererOut, nPageIndex, 72.0, 72.0, nRotate, gFalse, gTrue, gFalse);
((GlobalParamsAdaptor*)globalParams)->ClearRedact();
for (int i = 0 ; i < m_vRedact.size(); ++i)
{
if (m_vRedact[i]->m_nPageIndex == _nPageIndex)
{
IMetafileToRenderter* pCorrector = new IMetafileToRenderter(pRenderer);
NSOnlineOfficeBinToPdf::ConvertBufferToRenderer(m_vRedact[i]->m_pChanges, m_vRedact[i]->m_nChangeLength, pCorrector);
RELEASEOBJECT(pCorrector);
}
}
}
void CPdfReader::SetTempDirectory(const std::wstring& wsTempFolder)
{

View File

@ -94,6 +94,7 @@ public:
bool MergePages(const std::wstring& wsFile, const std::wstring& wsPassword = L"", int nMaxID = 0, const std::string& sPrefixForm = "");
bool UnmergePages();
bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* pChanges, int nLength);
bool UndoRedact();
void GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY);
void DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak);
std::wstring GetInfo();

View File

@ -182,6 +182,29 @@ bool GlobalParamsAdaptor::GetCMap(const char* sName, char*& pData, unsigned int&
return false;
}
void GlobalParamsAdaptor::AddRedact(const std::vector<double>& arrRedactBox)
{
m_arrRedactBox.insert(m_arrRedactBox.end(), arrRedactBox.begin(), arrRedactBox.end());
}
bool GlobalParamsAdaptor::InRedact(double dX, double dY)
{
for (int i = 0; i < m_arrRedactBox.size(); i += 8)
{
double xMin = m_arrRedactBox[i + 0];
double yMin = m_arrRedactBox[i + 1];
double xMax = m_arrRedactBox[i + 2];
double yMax = m_arrRedactBox[i + 3];
if (xMin < dX && dX < xMax && yMin < dY && dY < yMax)
return true;
}
return false;
}
void GlobalParamsAdaptor::ClearRedact()
{
m_arrRedactBox.clear();
}
bool operator==(const Ref &a, const Ref &b)
{
return a.gen == b.gen && a.num == b.num;

View File

@ -53,6 +53,7 @@
class GlobalParamsAdaptor : public GlobalParams
{
private:
std::wstring m_wsTempFolder;
std::wstring m_wsCMapFolder;
@ -60,6 +61,7 @@ class GlobalParamsAdaptor : public GlobalParams
DWORD m_nCMapDataLength;
bool m_bDrawFormField;
std::vector<double> m_arrRedactBox;
public:
GlobalParamsAdaptor(const char *filename) : GlobalParams(filename)
@ -92,6 +94,10 @@ public:
void setDrawFormField(bool bDrawFormField) { m_bDrawFormField = bDrawFormField; }
bool getDrawFormField() { return m_bDrawFormField; }
void AddRedact(const std::vector<double>& arrRedactBox);
bool InRedact(double dX, double dY);
void ClearRedact();
private:
void AddNameToUnicode(const char* sFile);

View File

@ -2381,6 +2381,9 @@ namespace PdfReader
return;
}
if (((GlobalParamsAdaptor*)globalParams)->InRedact(dX, dY))
return;
double* pCTM = pGState->getCTM();
double* pTm = pGState->getTextMat();
GfxFont* pFont = pGState->getFont();

View File

@ -376,13 +376,13 @@ void RedactOutputDev::drawChar(GfxState *pGState, double dX, double dY, double d
DoTransform(arrMatrix, &dShiftX, &dShiftY, true);
}
for (int i = 0; i < m_arrQuadPoints.size(); i += 8)
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
// TODO нужно учитывать m_arrMatrix, так ведь?
double xMin = m_arrQuadPoints[0];
double yMin = m_arrQuadPoints[1];
double xMax = m_arrQuadPoints[4];
double yMax = m_arrQuadPoints[5];
double xMin = m_arrQuadPoints[i + 0];
double yMin = m_arrQuadPoints[i + 1];
double xMax = m_arrQuadPoints[i + 2];
double yMax = m_arrQuadPoints[i + 3];
if (xMin < dX && dX < xMax && yMin < dY && dY < yMax)
return;
@ -523,12 +523,12 @@ void RedactOutputDev::drawForm(GfxState *pGState, Ref id, const char* name)
}
oBBox.free();
for (int i = 0; i < m_arrQuadPoints.size(); i += 8)
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
double xMin = m_arrQuadPoints[i + 0];
double yMin = m_arrQuadPoints[i + 1];
double xMax = m_arrQuadPoints[i + 4];
double yMax = m_arrQuadPoints[i + 5];
double xMax = m_arrQuadPoints[i + 2];
double yMax = m_arrQuadPoints[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return;
@ -749,12 +749,12 @@ void RedactOutputDev::DoPath(GfxState* pGState, GfxPath* pPath, double* pCTM, Gf
*/
pk::SkPath skPath, skPathRedact, skPathRes;
for (int i = 0; i < m_arrQuadPoints.size(); i += 8)
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 + 4], m_arrQuadPoints[i + 5]);
skPathRedact.lineTo(m_arrQuadPoints[i + 6], m_arrQuadPoints[i + 7]);
skPathRedact.lineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]);
skPathRedact.close();
}