mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
Fix EditPdf
This commit is contained in:
@ -647,7 +647,7 @@ void GetCTM(XRef* pXref, Object* oPage, double* dCTM)
|
||||
oContents.free();
|
||||
}
|
||||
|
||||
CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPassword, CPdfReader* _pReader, const std::wstring& _wsDstFile, CPdfWriter* _pWriter)
|
||||
CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPassword, const std::wstring& _wsDstFile, CPdfReader* _pReader, CPdfWriter* _pWriter)
|
||||
{
|
||||
m_wsSrcFile = _wsSrcFile;
|
||||
m_wsDstFile = _wsDstFile;
|
||||
@ -656,7 +656,7 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
m_pWriter = _pWriter;
|
||||
m_nEditPage = -1;
|
||||
m_nError = 0;
|
||||
m_nMode = 0;
|
||||
m_nMode = -1;
|
||||
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
if (!pPDFDocument)
|
||||
@ -665,7 +665,24 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
return;
|
||||
}
|
||||
|
||||
// Если результат редактирования будет сохранен в тот же файл, что открыт для чтения, то файл необходимо сделать редактируемым
|
||||
XRef* xref = pPDFDocument->getXRef();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
if (!xref || !pDoc)
|
||||
{
|
||||
m_nError = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bool CPdfEditor::IncrementalUpdates()
|
||||
{
|
||||
if (m_nMode == 0)
|
||||
return true;
|
||||
|
||||
m_nMode = 0;
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
XRef* xref = pPDFDocument->getXRef();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
|
||||
std::string sPathUtf8New = U_TO_UTF8(m_wsDstFile);
|
||||
std::string sPathUtf8Old = U_TO_UTF8(m_wsSrcFile);
|
||||
if (sPathUtf8Old == sPathUtf8New || NSSystemPath::NormalizePath(sPathUtf8Old) == NSSystemPath::NormalizePath(sPathUtf8New))
|
||||
@ -676,49 +693,30 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
delete owner_pswd;
|
||||
delete user_pswd;
|
||||
if (!bRes)
|
||||
{
|
||||
m_nError = 2; // Не удалось проверить файл для записи
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (!m_wsDstFile.empty())
|
||||
else
|
||||
{
|
||||
if (!NSFile::CFileBinary::Copy(m_wsSrcFile, m_wsDstFile))
|
||||
{
|
||||
m_nError = 2;
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
NSFile::CFileBinary oFile;
|
||||
if (!oFile.OpenFile(m_wsDstFile, true))
|
||||
{
|
||||
m_nError = 2;
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
oFile.CloseFile();
|
||||
}
|
||||
|
||||
XRef* xref = pPDFDocument->getXRef();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
if (!xref || !pDoc)
|
||||
{
|
||||
m_nError = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Получение каталога и дерева страниц из reader
|
||||
Object catDict, catRefObj, pagesRefObj;
|
||||
if (!xref->getCatalog(&catDict)->isDict() || !catDict.dictLookupNF("Pages", &pagesRefObj))
|
||||
{
|
||||
pagesRefObj.free(); catDict.free();
|
||||
m_nError = 3; // Не удалось получить каталог и дерево страниц
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
Object* trailer = xref->getTrailerDict();
|
||||
if (!trailer || !trailer->isDict() || !trailer->dictLookupNF("Root", &catRefObj)->isRef())
|
||||
{
|
||||
pagesRefObj.free(); catDict.free(); catRefObj.free();
|
||||
m_nError = 3; // Не удалось получить каталог и дерево страниц
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
Ref catRef = catRefObj.getRef();
|
||||
catRefObj.free();
|
||||
@ -728,15 +726,13 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
if (!pXref)
|
||||
{
|
||||
pagesRefObj.free(); catDict.free();
|
||||
m_nError = 1;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
PdfWriter::CCatalog* pCatalog = new PdfWriter::CCatalog();
|
||||
if (!pCatalog)
|
||||
{
|
||||
pagesRefObj.free(); catDict.free(); RELEASEOBJECT(pXref);
|
||||
m_nError = 1;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
pXref->Add(pCatalog, catRef.gen);
|
||||
PdfWriter::CResourcesDict* pDR = NULL;
|
||||
@ -884,8 +880,7 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
pagesRefObj.free();
|
||||
RELEASEOBJECT(pXref);
|
||||
RELEASEOBJECT(pDRXref);
|
||||
m_nError = 4; // Ошибка шифрования файла
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -901,49 +896,22 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
bRes = pDoc->EditResources(pDRXref, pDR);
|
||||
}
|
||||
pagesRefObj.free();
|
||||
if (!bRes)
|
||||
m_nError = 5; // Ошибка применения редактирования
|
||||
}
|
||||
CPdfEditor::CPdfEditor(CPdfReader* _pReader, CPdfWriter* _pWriter)
|
||||
{
|
||||
m_pReader = _pReader;
|
||||
m_pWriter = _pWriter;
|
||||
m_nEditPage = -1;
|
||||
m_nError = 0;
|
||||
m_nMode = 1;
|
||||
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
if (!pPDFDocument)
|
||||
{
|
||||
m_nError = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
XRef* xref = pPDFDocument->getXRef();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
if (!xref || !pDoc)
|
||||
{
|
||||
m_nError = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
int CPdfEditor::Close(const std::wstring& wsPath)
|
||||
{
|
||||
m_wsDstFile = wsPath;
|
||||
Close();
|
||||
return 0;
|
||||
return bRes;
|
||||
}
|
||||
void CPdfEditor::Close()
|
||||
{
|
||||
if (m_nMode != 0 || m_wsDstFile.empty())
|
||||
if (m_wsDstFile.empty())
|
||||
return;
|
||||
|
||||
if (m_nMode == 1)
|
||||
{
|
||||
m_pWriter->SaveToFile(m_wsDstFile);
|
||||
return;
|
||||
}
|
||||
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
if (!pPDFDocument || !pDoc)
|
||||
return;
|
||||
XRef* xref = pPDFDocument->getXRef();
|
||||
if (!xref)
|
||||
return;
|
||||
|
||||
// Добавляем первый элемент в таблицу xref
|
||||
// он должен иметь вид 0000000000 65535 f
|
||||
@ -1127,6 +1095,9 @@ void CPdfEditor::GetPageTree(XRef* xref, Object* pPagesRefObj, PdfWriter::CPageT
|
||||
}
|
||||
bool CPdfEditor::EditPage(int nPageIndex, bool bSet)
|
||||
{
|
||||
if (m_nMode != 0 && !IncrementalUpdates())
|
||||
return false;
|
||||
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
if (!pPDFDocument || !pDoc)
|
||||
@ -1284,13 +1255,16 @@ bool CPdfEditor::EditPage(int nPageIndex, bool bSet)
|
||||
}
|
||||
bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength)
|
||||
{
|
||||
if (m_nMode >= 0)
|
||||
return false;
|
||||
m_nMode = 1;
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
XRef* xref = pPDFDocument->getXRef();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
|
||||
// Страницы должны быть созданы заранее для ссылки
|
||||
Catalog* pCatalog = pPDFDocument->getCatalog();
|
||||
for (int i = 0; i < unLength; ++i)
|
||||
for (unsigned int i = 0; i < unLength; ++i)
|
||||
{
|
||||
Ref* pPageRef = pCatalog->getPageRef(arrPageIndex[i] + 1);
|
||||
if (pPageRef->num == 0)
|
||||
@ -1316,6 +1290,7 @@ bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength)
|
||||
m_mSplitUniqueRef[pPageRef->num] = pPage;
|
||||
pageRefObj.free();
|
||||
}
|
||||
|
||||
bool bRes = true;
|
||||
for (unsigned int i = 0; i < unLength; ++i)
|
||||
bRes &= SplitPage(arrPageIndex[i]);
|
||||
@ -1494,10 +1469,16 @@ bool CPdfEditor::SplitPage(int nPageIndex)
|
||||
}
|
||||
bool CPdfEditor::DeletePage(int nPageIndex)
|
||||
{
|
||||
if (m_nMode != 0 && !IncrementalUpdates())
|
||||
return false;
|
||||
|
||||
return m_pWriter->GetDocument()->DeletePage(nPageIndex);
|
||||
}
|
||||
bool CPdfEditor::AddPage(int nPageIndex)
|
||||
{
|
||||
if (m_nMode != 0 && !IncrementalUpdates())
|
||||
return false;
|
||||
|
||||
// Применение добавления страницы для writer
|
||||
if (!m_pWriter->AddPage(nPageIndex))
|
||||
return false;
|
||||
@ -1837,6 +1818,9 @@ bool CPdfEditor::DeleteAnnot(int nID, Object* oAnnots)
|
||||
}
|
||||
bool CPdfEditor::EditWidgets(IAdvancedCommand* pCommand)
|
||||
{
|
||||
if (m_nMode != 0 && !IncrementalUpdates())
|
||||
return false;
|
||||
|
||||
CWidgetsInfo* pFieldInfo = (CWidgetsInfo*)pCommand;
|
||||
PDFDoc* pPDFDocument = m_pReader->GetPDFDocument();
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
|
||||
@ -40,12 +40,12 @@ HRESULT _ChangePassword(const std::wstring& wsPath, const std::wstring& wsPasswo
|
||||
class CPdfEditor
|
||||
{
|
||||
public:
|
||||
CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPassword, CPdfReader* _pReader, const std::wstring& _wsDstFile, CPdfWriter* _pWriter);
|
||||
CPdfEditor(CPdfReader* _pReader, CPdfWriter* _pWriter);
|
||||
CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPassword, const std::wstring& _wsDstFile, CPdfReader* _pReader, CPdfWriter* _pWriter);
|
||||
|
||||
bool IncrementalUpdates();
|
||||
|
||||
int GetError();
|
||||
void Close();
|
||||
int Close(const std::wstring& wsPath);
|
||||
bool EditPage(int nPageIndex, bool bSet = true);
|
||||
bool DeletePage(int nPageIndex);
|
||||
bool AddPage(int nPageIndex);
|
||||
@ -61,10 +61,10 @@ public:
|
||||
void EndMarkedContent();
|
||||
bool IsBase14(const std::wstring& wsFontName, bool& bBold, bool& bItalic, std::wstring& wsFontPath);
|
||||
|
||||
bool SplitPage(int nPageIndex);
|
||||
bool SplitPages(const int* arrPageIndex, unsigned int unLength);
|
||||
|
||||
private:
|
||||
bool SplitPage(int nPageIndex);
|
||||
void GetPageTree(XRef* xref, Object* pPagesRefObj, PdfWriter::CPageTree* pPageParent = NULL);
|
||||
|
||||
std::wstring m_wsSrcFile;
|
||||
|
||||
@ -133,18 +133,14 @@ void CPdfFile::RotatePage(int nRotate)
|
||||
#ifndef BUILDING_WASM_MODULE
|
||||
bool CPdfFile::EditPdf(const std::wstring& wsDstFile)
|
||||
{
|
||||
if (wsDstFile.empty())
|
||||
if (wsDstFile.empty() || !m_pInternal->pReader)
|
||||
return false;
|
||||
|
||||
if (!m_pInternal->pReader)
|
||||
return false;
|
||||
|
||||
// Создание writer для редактирования
|
||||
RELEASEOBJECT(m_pInternal->pWriter);
|
||||
m_pInternal->pWriter = new CPdfWriter(m_pInternal->pAppFonts, false, this);
|
||||
|
||||
RELEASEOBJECT(m_pInternal->pEditor);
|
||||
m_pInternal->pEditor = new CPdfEditor(m_pInternal->wsSrcFile, m_pInternal->wsPassword, m_pInternal->pReader, wsDstFile, m_pInternal->pWriter);
|
||||
m_pInternal->pEditor = new CPdfEditor(m_pInternal->wsSrcFile, m_pInternal->wsPassword, wsDstFile, m_pInternal->pReader, m_pInternal->pWriter);
|
||||
return m_pInternal->pEditor->GetError() == 0;
|
||||
}
|
||||
bool CPdfFile::EditPage(int nPageIndex)
|
||||
@ -168,42 +164,14 @@ bool CPdfFile::AddPage(int nPageIndex)
|
||||
bool CPdfFile::SplitPages(const int* arrPageIndex, unsigned int unLength)
|
||||
{
|
||||
if (!m_pInternal->pEditor)
|
||||
{
|
||||
if (!m_pInternal->pReader)
|
||||
return false;
|
||||
|
||||
if (!m_pInternal->pWriter)
|
||||
m_pInternal->pWriter = new CPdfWriter(m_pInternal->pAppFonts, false, this);
|
||||
|
||||
m_pInternal->pEditor = new CPdfEditor(m_pInternal->pReader, m_pInternal->pWriter);
|
||||
if (m_pInternal->pEditor->GetError() != 0)
|
||||
return false;
|
||||
}
|
||||
return m_pInternal->pEditor->SplitPages(arrPageIndex, unLength);
|
||||
}
|
||||
bool CPdfFile::MergePages(CPdfFile* pMergeFile, const int* arrPageIndex, unsigned int unLength, int nMergePos)
|
||||
{
|
||||
if (!pMergeFile || !pMergeFile->m_pInternal || !pMergeFile->m_pInternal->pReader)
|
||||
return false;
|
||||
|
||||
if (!m_pInternal->pEditor)
|
||||
{
|
||||
if (!m_pInternal->pReader)
|
||||
return false;
|
||||
|
||||
if (!m_pInternal->pWriter)
|
||||
m_pInternal->pWriter = new CPdfWriter(m_pInternal->pAppFonts, false, this);
|
||||
|
||||
m_pInternal->pEditor = new CPdfEditor(m_pInternal->wsSrcFile, m_pInternal->wsPassword, m_pInternal->pReader, L"", m_pInternal->pWriter);
|
||||
if (m_pInternal->pEditor->GetError() != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO
|
||||
return m_pInternal->pEditor->SplitPages(arrPageIndex, unLength);
|
||||
}
|
||||
bool CPdfFile::MergePages(const std::wstring& wsPath, const std::wstring& wsPassword, const int* arrPageIndex, unsigned int unLength, int nMergePos)
|
||||
{
|
||||
if (!m_pInternal->pEditor)
|
||||
return false;
|
||||
|
||||
CPdfFile* pMergeFile = new CPdfFile(m_pInternal->pAppFonts);
|
||||
pMergeFile->SetTempDirectory(m_pInternal->wsTempFolder);
|
||||
|
||||
@ -213,7 +181,7 @@ bool CPdfFile::MergePages(const std::wstring& wsPath, const std::wstring& wsPass
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bRes = MergePages(pMergeFile, arrPageIndex, unLength, nMergePos);
|
||||
bool bRes = m_pInternal->pEditor->SplitPages(arrPageIndex, unLength);
|
||||
RELEASEOBJECT(pMergeFile);
|
||||
return bRes;
|
||||
}
|
||||
@ -530,8 +498,6 @@ int CPdfFile::SaveToFile(const std::wstring& wsPath)
|
||||
{
|
||||
if (!m_pInternal->pWriter)
|
||||
return 1;
|
||||
if (m_pInternal->pEditor)
|
||||
return m_pInternal->pEditor->Close(wsPath);
|
||||
return m_pInternal->pWriter->SaveToFile(wsPath);
|
||||
}
|
||||
void CPdfFile::SetPassword(const std::wstring& wsPassword)
|
||||
|
||||
@ -98,7 +98,6 @@ public:
|
||||
bool DeletePage(int nPageIndex);
|
||||
bool AddPage (int nPageIndex);
|
||||
bool SplitPages(const int* arrPageIndex, unsigned int unLength);
|
||||
bool MergePages(CPdfFile* pMergeFile, const int* arrPageIndex = NULL, unsigned int unLength = 0, int nMergePos = -1);
|
||||
bool MergePages(const std::wstring& wsPath, const std::wstring& wsPassword = L"", const int* arrPageIndex = NULL, unsigned int unLength = 0, int nMergePos = -1);
|
||||
HRESULT ChangePassword(const std::wstring& wsPath, const std::wstring& wsPassword = L"");
|
||||
#endif
|
||||
|
||||
@ -355,16 +355,17 @@ TEST_F(CPdfFileTest, SplitPdf)
|
||||
//GTEST_SKIP();
|
||||
|
||||
LoadFromFile();
|
||||
ASSERT_TRUE(pdfFile->EditPdf(wsDstFile));
|
||||
|
||||
std::vector<int> arrPages = { 0, 1, 2, 3 };
|
||||
std::vector<int> arrPages = { 0 };
|
||||
pdfFile->SplitPages(arrPages.empty() ? NULL : arrPages.data(), arrPages.size());
|
||||
|
||||
pdfFile->SaveToFile(wsDstFile);
|
||||
pdfFile->Close();
|
||||
}
|
||||
|
||||
TEST_F(CPdfFileTest, MergePdf)
|
||||
{
|
||||
//GTEST_SKIP();
|
||||
GTEST_SKIP();
|
||||
|
||||
LoadFromFile();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user