Merge pull request 'Fix SplitPages with changes' (#294) from fix/pdf-split into release/v9.0.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/294
This commit is contained in:
Oleg Korshul
2025-04-29 10:53:41 +00:00
14 changed files with 110 additions and 51 deletions

View File

@ -283,10 +283,10 @@ public:
return NULL;
return m_pFile->ConvertToPixels(nPageIndex, nRasterW, nRasterH, true, m_pFontManager, nBackgroundColor, (nBackgroundColor == 0xFFFFFF) ? false : true);
}
BYTE* SplitPages(int* arrPageIndex, int nLength)
BYTE* SplitPages(int* arrPageIndex, int nLength, BYTE* data, LONG size)
{
if (m_nType == 0)
return ((CPdfFile*)m_pFile)->SplitPages(arrPageIndex, nLength);
return ((CPdfFile*)m_pFile)->SplitPages(arrPageIndex, nLength, data, size);
return NULL;
}
bool MergePages(BYTE* data, LONG size, int nMaxID, const std::string& sPrefixForm)

View File

@ -186,7 +186,7 @@
},
{
"folder": "../../../../PdfFile/",
"files": ["PdfFile.cpp", "PdfReader.cpp", "PdfWriter.cpp", "PdfEditor.cpp"]
"files": ["PdfFile.cpp", "PdfReader.cpp", "PdfWriter.cpp", "PdfEditor.cpp", "OnlineOfficeBinToPdf.cpp"]
},
{
"folder": "../../../../PdfFile/SrcReader/",

View File

@ -145,9 +145,9 @@ CFile.prototype["isNeedPassword"] = function()
{
return this._isNeedPassword;
};
CFile.prototype["SplitPages"] = function(arrPageIndex)
CFile.prototype["SplitPages"] = function(arrPageIndex, arrayBufferChanges)
{
let ptr = this._SplitPages(arrPageIndex);
let ptr = this._SplitPages(arrPageIndex, arrayBufferChanges);
if (!ptr)
return null;

View File

@ -121,12 +121,24 @@ CFile.prototype._getError = function()
return Module["_GetErrorCode"](this.nativeFile);
};
CFile.prototype._SplitPages = function(memoryBuffer)
CFile.prototype._SplitPages = function(memoryBuffer, 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 pointer = Module["_malloc"](memoryBuffer.length * 4);
Module["HEAP32"].set(memoryBuffer, pointer >> 2);
let ptr = Module["_SplitPages"](this.nativeFile, pointer, memoryBuffer.length);
let ptr = Module["_SplitPages"](this.nativeFile, pointer, memoryBuffer.length, changesPtr, changesLen);
Module["_free"](pointer);
if (changesPtr)
Module["_free"](changesPtr);
return ptr;
};

View File

@ -177,9 +177,9 @@ WASM_EXPORT BYTE* ScanPage(CDrawingFile* pFile, int nPageIndex, int mode)
{
return pFile->ScanPage(nPageIndex, mode);
}
WASM_EXPORT BYTE* SplitPages(CDrawingFile* pFile, int* arrPageIndex, int nLength)
WASM_EXPORT BYTE* SplitPages(CDrawingFile* pFile, int* arrPageIndex, int nLength, BYTE* data, LONG size)
{
return pFile->SplitPages(arrPageIndex, nLength);
return pFile->SplitPages(arrPageIndex, nLength, data, size);
}
WASM_EXPORT int MergePages(CDrawingFile* pFile, BYTE* data, LONG size, int nMaxID, const char* sPrefixForm)
{

View File

@ -993,12 +993,12 @@ int main(int argc, char* argv[])
// SPLIT & MERGE
BYTE* pSplitPages = NULL;
if (true)
if (false)
{
std::vector<int> arrPages = { 0 };
for (int i = 0; i < 3; i++)
{
pSplitPages = SplitPages(pGrFile, arrPages.data(), arrPages.size());
pSplitPages = SplitPages(pGrFile, arrPages.data(), arrPages.size(), NULL, 0);
if (pSplitPages)
{
int nLength = READ_INT(pSplitPages);

View File

@ -1373,7 +1373,7 @@ void CPdfEditor::GetPageTree(XRef* xref, Object* pPagesRefObj, PdfWriter::CPageT
}
bool CPdfEditor::EditPage(int _nPageIndex, bool bSet, bool bActualPos)
{
if (m_nMode != Mode::WriteAppend && !IncrementalUpdates())
if (m_nMode == Mode::Unknown && !IncrementalUpdates())
return false;
PDFDoc* pPDFDocument = NULL;
@ -1387,6 +1387,8 @@ bool CPdfEditor::EditPage(int _nPageIndex, bool bSet, bool bActualPos)
PdfWriter::CPage* pEditPage = NULL;
pEditPage = bActualPos ? pDoc->GetPage(_nPageIndex) : pDoc->GetEditPage(_nPageIndex);
if (m_nMode == Mode::WriteNew && !pEditPage)
return false;
if (pEditPage)
{
if (bSet)
@ -1546,10 +1548,8 @@ bool CPdfEditor::EditPage(int _nPageIndex, bool bSet, bool bActualPos)
}
bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength, PDFDoc* _pDoc, int nStartRefID)
{
if (m_nMode == Mode::WriteNew)
return false;
if (m_nMode == Mode::Unknown)
m_nMode = Mode::WriteNew;
return false;
PDFDoc* pPDFDocument = _pDoc;
XRef* xref = pPDFDocument->getXRef();
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
@ -1569,7 +1569,7 @@ bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength, PDFD
PdfWriter::CPage* pPage = new PdfWriter::CPage(pDoc);
pDoc->AddObject(pPage);
pDoc->AddPage(pDoc->GetPagesCount(), pPage);
pDoc->AddEditPage(pPage, nPagesBefore + i);
pDoc->AddEditPage(pPage, nPagesBefore + (arrPageIndex ? arrPageIndex[i] : i));
// Получение объекта страницы
Object pageRefObj, pageObj;
@ -1909,13 +1909,15 @@ bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength, PDFD
return true;
}
BYTE* CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength)
bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength)
{
if (m_nMode != Mode::Unknown)
return NULL;
if (m_nMode == Mode::WriteNew)
return false;
if (m_nMode == Mode::Unknown)
m_nMode = Mode::WriteNew;
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
if (!pDoc)
return NULL;
return false;
int nTotalPages = 0;
int nPDFIndex = 0;
@ -1941,26 +1943,9 @@ BYTE* CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength)
{
pPDFDocument = m_pReader->GetPDFDocument(it.first);
if (!SplitPages(it.second.data(), it.second.size(), pPDFDocument, m_pReader->GetStartRefID(pPDFDocument)))
return NULL;
return false;
}
BYTE* pRes = NULL;
int nLength = 0;
if (m_pWriter->SaveToMemory(&pRes, &nLength) == 0)
{
NSWasm::CData oRes;
oRes.SkipLen();
oRes.Write(pRes, nLength);
RELEASEARRAYOBJECTS(pRes);
oRes.WriteLen();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return bRes;
}
RELEASEARRAYOBJECTS(pRes);
return NULL;
return true;
}
void CreateOutlines(PDFDoc* pdfDoc, PdfWriter::CDocument* pDoc, OutlineItem* pOutlineItem, PdfWriter::COutline* pParent)
{
@ -2133,7 +2118,7 @@ bool CPdfEditor::DeletePage(int nPageIndex)
}
bool CPdfEditor::AddPage(int nPageIndex)
{
if (m_nMode != Mode::WriteAppend && !IncrementalUpdates())
if (m_nMode == Mode::Unknown && !IncrementalUpdates())
return false;
// Применение добавления страницы для writer
@ -2462,6 +2447,8 @@ bool CPdfEditor::DeleteAnnot(int nID, Object* oAnnots)
pObj->SetHidden();
return true;
}
if (m_nMode == Mode::WriteNew)
return true;
PDFDoc* pPDFDocument = NULL;
int nPageIndex = m_pReader->GetPageIndex(m_nEditPage, &pPDFDocument);
@ -2690,7 +2677,7 @@ bool CPdfEditor::DeleteAnnot(int nID, Object* oAnnots)
}
bool CPdfEditor::EditWidgets(IAdvancedCommand* pCommand)
{
if (m_nMode != Mode::WriteAppend && !IncrementalUpdates())
if (m_nMode == Mode::Unknown && !IncrementalUpdates())
return false;
CWidgetsInfo* pFieldInfo = (CWidgetsInfo*)pCommand;

View File

@ -93,7 +93,7 @@ public:
void EndMarkedContent();
bool IsBase14(const std::wstring& wsFontName, bool& bBold, bool& bItalic, std::wstring& wsFontPath);
BYTE* SplitPages(const int* arrPageIndex, unsigned int unLength);
bool SplitPages(const int* arrPageIndex, unsigned int unLength);
bool MergePages(const std::wstring& wsPath, const std::wstring& wsPrefixForm);
private:

View File

@ -429,7 +429,7 @@ BYTE* CPdfFile::GetAnnots(int nPageIndex)
return NULL;
return m_pInternal->pReader->GetAnnots(nPageIndex);
}
BYTE* CPdfFile::SplitPages(const int* arrPageIndex, unsigned int unLength)
BYTE* CPdfFile::SplitPages(const int* arrPageIndex, unsigned int unLength, BYTE* pChanges, DWORD nLength)
{
if (!m_pInternal->pReader)
return NULL;
@ -439,7 +439,23 @@ BYTE* CPdfFile::SplitPages(const int* arrPageIndex, unsigned int unLength)
RELEASEOBJECT(m_pInternal->pEditor);
m_pInternal->pEditor = new CPdfEditor(m_pInternal->wsSrcFile, m_pInternal->wsPassword, L"", m_pInternal->pReader, m_pInternal->pWriter);
BYTE* pRes = m_pInternal->pEditor->SplitPages(arrPageIndex, unLength);
BYTE* pRes = NULL;
int nLen = 0;
if (m_pInternal->pEditor->SplitPages(arrPageIndex, unLength))
{
if (pChanges)
{
CConvertFromBinParams* pParams = new CConvertFromBinParams();
AddToPdfFromBinary(pChanges + 4, nLength - 4, pParams);
}
if (m_pInternal->pWriter->SaveToMemory(&pRes, &nLen) != 0)
{
RELEASEMEM(pRes);
}
else
pRes = m_pInternal->pReader->StreamToCData(pRes, nLen);
}
RELEASEOBJECT(m_pInternal->pWriter);
RELEASEOBJECT(m_pInternal->pEditor);

View File

@ -135,7 +135,7 @@ public:
BYTE* GetAnnotEmbeddedFonts();
BYTE* GetAnnotStandardFonts();
BYTE* GetAnnots (int nPageIndex = -1);
BYTE* SplitPages (const int* arrPageIndex, unsigned int unLength);
BYTE* SplitPages (const int* arrPageIndex, unsigned int unLength, BYTE* pChanges = NULL, DWORD nLength = 0);
BYTE* VerifySign (const std::wstring& sFile, ICertificate* pCertificate, int nWidget = -1);
BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL);
BYTE* GetAPAnnots (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL);

View File

@ -1670,6 +1670,19 @@ BYTE* CPdfReader::GetButtonIcon(int nBackgroundColor, int _nPageIndex, bool bBas
oRes.ClearWithoutAttack();
return bRes;
}
BYTE* CPdfReader::StreamToCData(BYTE* pSteam, int nLength)
{
NSWasm::CData oRes;
oRes.SkipLen();
oRes.Write(pSteam, nLength);
oRes.WriteLen();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return bRes;
}
int GetPageAnnots(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, PdfReader::CPdfFontList *pFontList, NSWasm::CData& oRes, int nPageIndex, int nStartPage, int nStartRefID)
{
Page* pPage = pdfDoc->getCatalog()->getPage(nPageIndex);

View File

@ -103,6 +103,7 @@ public:
BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL);
BYTE* GetAPAnnots (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL);
BYTE* GetButtonIcon(int nBackgroundColor, int nPageIndex, bool bBase64 = false, int nBWidget = -1, const char* sIView = NULL);
BYTE* StreamToCData(BYTE* pSteam, int nLength);
const std::map<std::wstring, std::wstring>& GetFonts() { return m_mFonts; }
private:

View File

@ -249,6 +249,7 @@ namespace PdfWriter
*pData = pStream->GetBuffer();
*pLength = pStream->Size();
pStream->ClearWithoutAttack();
return true;
}

View File

@ -352,23 +352,52 @@ TEST_F(CPdfFileTest, VerifySign)
TEST_F(CPdfFileTest, SplitPdf)
{
GTEST_SKIP();
//GTEST_SKIP();
LoadFromFile();
std::vector<int> arrPages = { 0 };
BYTE* pFile = pdfFile->SplitPages(arrPages.data(), arrPages.size());
int nBufferLen = NULL;
BYTE* pBuffer = NULL;
NSFile::CFileBinary oFile;
if (oFile.OpenFile(NSFile::GetProcessDirectory() + L"/base64.txt"))
{
DWORD dwFileSize = oFile.GetFileSize();
BYTE* pFileContent = new BYTE[dwFileSize];
if (!pFileContent)
{
oFile.CloseFile();
FAIL();
}
DWORD dwReaded;
EXPECT_TRUE(oFile.ReadFile(pFileContent, dwFileSize, dwReaded));
nBufferLen = NSBase64::Base64DecodeGetRequiredLength(dwFileSize);
pBuffer = new BYTE[nBufferLen];
if (!pBuffer)
{
RELEASEARRAYOBJECTS(pFileContent);
FAIL();
}
EXPECT_TRUE(NSBase64::Base64Decode((const char*)pFileContent, dwFileSize, pBuffer, &nBufferLen));
}
oFile.CloseFile();
std::vector<int> arrPages = { 1 };
BYTE* pFile = pdfFile->SplitPages(arrPages.data(), arrPages.size(), pBuffer, nBufferLen);
ASSERT_TRUE(pFile != NULL);
NSFile::CFileBinary oFile;
std::wstring wsSplitFile = NSFile::GetProcessDirectory() + L"/test_split.pdf";
if (oFile.CreateFileW(wsSplitFile))
{
int nLength = pFile[0] | pFile[1] << 8 | pFile[2] << 16 | pFile[3] << 24;
oFile.WriteFile(pFile + 4, nLength);
oFile.WriteFile(pFile + 4, nLength - 4);
}
oFile.CloseFile();
RELEASEARRAYOBJECTS(pFile);
RELEASEARRAYOBJECTS(pBuffer);
}
TEST_F(CPdfFileTest, MergePdf)
@ -407,7 +436,7 @@ TEST_F(CPdfFileTest, EditPdf)
TEST_F(CPdfFileTest, EditPdfFromBase64)
{
//GTEST_SKIP();
GTEST_SKIP();
NSFonts::NSApplicationFontStream::SetGlobalMemoryStorage(NSFonts::NSApplicationFontStream::CreateDefaultGlobalMemoryStorage());