mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
Merge Outlines two files
This commit is contained in:
@ -40,12 +40,16 @@
|
||||
#include "lib/xpdf/TextString.h"
|
||||
#include "lib/xpdf/Lexer.h"
|
||||
#include "lib/xpdf/Parser.h"
|
||||
#include "lib/xpdf/Outline.h"
|
||||
#include "lib/xpdf/Link.h"
|
||||
|
||||
#include "SrcWriter/Catalog.h"
|
||||
#include "SrcWriter/EncryptDictionary.h"
|
||||
#include "SrcWriter/Info.h"
|
||||
#include "SrcWriter/ResourcesDictionary.h"
|
||||
#include "SrcWriter/Streams.h"
|
||||
#include "SrcWriter/Destination.h"
|
||||
#include "SrcWriter/Outline.h"
|
||||
|
||||
#define AddToObject(oVal)\
|
||||
{\
|
||||
@ -929,7 +933,7 @@ CPdfEditor::CPdfEditor(const std::wstring& _wsSrcFile, const std::wstring& _wsPa
|
||||
}
|
||||
bool CPdfEditor::IncrementalUpdates()
|
||||
{
|
||||
if (m_nMode == Mode::Unknown)
|
||||
if (m_nMode != Mode::Unknown)
|
||||
return true;
|
||||
|
||||
m_nMode = Mode::WriteAppend;
|
||||
@ -1157,7 +1161,7 @@ void CPdfEditor::Close()
|
||||
if (m_wsDstFile.empty())
|
||||
return;
|
||||
|
||||
if (m_nMode == Mode::WriteAppend)
|
||||
if (m_nMode != Mode::WriteAppend)
|
||||
{
|
||||
m_pWriter->SaveToFile(m_wsDstFile);
|
||||
return;
|
||||
@ -1894,7 +1898,106 @@ BYTE* CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength)
|
||||
RELEASEARRAYOBJECTS(pRes);
|
||||
return NULL;
|
||||
}
|
||||
bool CPdfEditor::MergePages(const int* arrPageIndex, unsigned int unLength)
|
||||
void CreateOutlines(PDFDoc* pdfDoc, PdfWriter::CDocument* pDoc, OutlineItem* pOutlineItem, PdfWriter::COutline* pParent)
|
||||
{
|
||||
std::string sTitle = NSStringExt::CConverter::GetUtf8FromUTF32(pOutlineItem->getTitle(), pOutlineItem->getTitleLength());
|
||||
PdfWriter::COutline* pOutline = pDoc->CreateOutline(pParent, sTitle.c_str());
|
||||
|
||||
PdfWriter::CDestination* pDest = NULL;
|
||||
LinkAction* pLinkAction = pOutlineItem->getAction();
|
||||
if (pLinkAction && pLinkAction->getKind() == actionGoTo)
|
||||
{
|
||||
GString* str = ((LinkGoTo*)pLinkAction)->getNamedDest();
|
||||
LinkDest* pLinkDest = str ? pdfDoc->findDest(str) : ((LinkGoTo*)pLinkAction)->getDest();
|
||||
if (pLinkDest)
|
||||
{
|
||||
int pg;
|
||||
if (pLinkDest->isPageRef())
|
||||
{
|
||||
Ref pageRef = pLinkDest->getPageRef();
|
||||
pg = pdfDoc->findPage(pageRef.num, pageRef.gen);
|
||||
}
|
||||
else
|
||||
pg = pLinkDest->getPageNum();
|
||||
if (pg == 0)
|
||||
pg = 1;
|
||||
|
||||
Ref* pPageRef = pdfDoc->getCatalog()->getPageRef(pg);
|
||||
PdfWriter::CObjectBase* pPageD = pDoc->GetEditPage(--pg);
|
||||
if (!pPageD && pPageRef->num > 0)
|
||||
{
|
||||
PdfWriter::CObjectBase* pBase = new PdfWriter::CObjectBase();
|
||||
pBase->SetRef(pPageRef->num, pPageRef->gen);
|
||||
pPageD = new PdfWriter::CProxyObject(pBase, true);
|
||||
}
|
||||
pDest = pDoc->CreateDestination(pPageD, true);
|
||||
|
||||
switch (pLinkDest->getKind())
|
||||
{
|
||||
case destXYZ:
|
||||
{
|
||||
pDest->SetXYZ(pLinkDest->getLeft(), pLinkDest->getTop(), pLinkDest->getZoom());
|
||||
break;
|
||||
}
|
||||
case destFit:
|
||||
{
|
||||
pDest->SetFit();
|
||||
break;
|
||||
}
|
||||
case destFitH:
|
||||
{
|
||||
pDest->SetFitH(pLinkDest->getTop());
|
||||
break;
|
||||
}
|
||||
case destFitV:
|
||||
{
|
||||
pDest->SetFitV(pLinkDest->getLeft());
|
||||
break;
|
||||
}
|
||||
case destFitR:
|
||||
{
|
||||
pDest->SetFitR(pLinkDest->getLeft(), pLinkDest->getBottom(), pLinkDest->getRight(), pLinkDest->getTop());
|
||||
break;
|
||||
}
|
||||
case destFitB:
|
||||
{
|
||||
pDest->SetFitB();
|
||||
break;
|
||||
}
|
||||
case destFitBH:
|
||||
{
|
||||
pDest->SetFitBH(pLinkDest->getTop());
|
||||
break;
|
||||
}
|
||||
case destFitBV:
|
||||
{
|
||||
pDest->SetFitBV(pLinkDest->getLeft());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (str)
|
||||
RELEASEOBJECT(pLinkDest);
|
||||
}
|
||||
if (pDest)
|
||||
pOutline->SetDestination(pDest);
|
||||
|
||||
pOutlineItem->open();
|
||||
GList* pList = pOutlineItem->getKids();
|
||||
if (!pList)
|
||||
{
|
||||
pOutlineItem->close();
|
||||
return;
|
||||
}
|
||||
for (int i = 0, num = pList->getLength(); i < num; i++)
|
||||
{
|
||||
OutlineItem* pOutlineItemKid = (OutlineItem*)pList->get(i);
|
||||
if (pOutlineItemKid)
|
||||
CreateOutlines(pdfDoc, pDoc, pOutlineItemKid, pOutline);
|
||||
}
|
||||
pOutlineItem->close();
|
||||
}
|
||||
bool CPdfEditor::MergePages(const std::wstring& wsPath, const int* arrPageIndex, unsigned int unLength)
|
||||
{
|
||||
if (m_nMode != Mode::WriteAppend && !IncrementalUpdates())
|
||||
return false;
|
||||
@ -1904,6 +2007,39 @@ bool CPdfEditor::MergePages(const int* arrPageIndex, unsigned int unLength)
|
||||
if (!bRes)
|
||||
return false;
|
||||
|
||||
Outline* pOutlineAdd = pDocument->getOutline();
|
||||
GList* pListAdd = NULL;
|
||||
if (pOutlineAdd)
|
||||
pListAdd = pOutlineAdd->getItems();
|
||||
if (!pListAdd)
|
||||
return bRes;
|
||||
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
PDFDoc* pDocumentFirst = m_pReader->GetPDFDocument(0);
|
||||
Outline* pOutlineOld = pDocumentFirst->getOutline();
|
||||
GList* pListOld = NULL;
|
||||
if (pOutlineOld)
|
||||
pListOld = pOutlineOld->getItems();
|
||||
if (!pDoc->GetOutlines() && pListOld)
|
||||
{
|
||||
for (int i = 0, num = pListOld->getLength(); i < num; i++)
|
||||
{
|
||||
OutlineItem* pOutlineItem = (OutlineItem*)pListOld->get(i);
|
||||
if (pOutlineItem)
|
||||
CreateOutlines(pDocumentFirst, pDoc, pOutlineItem, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring wsFileName = NSFile::GetFileName(wsPath);
|
||||
std::string sFileName = U_TO_UTF8(wsFileName);
|
||||
PdfWriter::COutline* pOutline = pDoc->CreateOutline(NULL, sFileName.c_str());
|
||||
for (int i = 0, num = pListAdd->getLength(); i < num; i++)
|
||||
{
|
||||
OutlineItem* pOutlineItem = (OutlineItem*)pListAdd->get(i);
|
||||
if (pOutlineItem)
|
||||
CreateOutlines(pDocumentFirst, pDoc, pOutlineItem, pOutline);
|
||||
}
|
||||
|
||||
return bRes;
|
||||
}
|
||||
bool CPdfEditor::DeletePage(int nPageIndex)
|
||||
|
||||
@ -94,7 +94,7 @@ public:
|
||||
bool IsBase14(const std::wstring& wsFontName, bool& bBold, bool& bItalic, std::wstring& wsFontPath);
|
||||
|
||||
BYTE* SplitPages(const int* arrPageIndex, unsigned int unLength);
|
||||
bool MergePages(const int* arrPageIndex, unsigned int unLength);
|
||||
bool MergePages(const std::wstring& wsPath, const int* arrPageIndex, unsigned int unLength);
|
||||
|
||||
private:
|
||||
void GetPageTree(XRef* xref, Object* pPagesRefObj, PdfWriter::CPageTree* pPageParent = NULL);
|
||||
|
||||
@ -32,13 +32,12 @@
|
||||
#include "PdfFile.h"
|
||||
#include "PdfWriter.h"
|
||||
#include "PdfReader.h"
|
||||
#include "PdfEditor.h"
|
||||
|
||||
#include "../DesktopEditor/common/File.h"
|
||||
#include "../DesktopEditor/graphics/commands/DocInfo.h"
|
||||
#include "lib/xpdf/PDFDoc.h"
|
||||
#include "Resources/BaseFonts.h"
|
||||
|
||||
#include "PdfEditor.h"
|
||||
#include "OnlineOfficeBinToPdf.h"
|
||||
#include "SrcWriter/Document.h"
|
||||
|
||||
@ -141,7 +140,7 @@ bool CPdfFile::MergePages(const std::wstring& wsPath, const std::wstring& wsPass
|
||||
if (!m_pInternal->pEditor)
|
||||
return false;
|
||||
if (m_pInternal->pReader->MergePages(wsPath, wsPassword))
|
||||
return m_pInternal->pEditor->MergePages(arrPageIndex, unLength);
|
||||
return m_pInternal->pEditor->MergePages(wsPath, arrPageIndex, unLength);
|
||||
return false;
|
||||
}
|
||||
bool CPdfFile::MovePage(int nPageIndex, int nPos)
|
||||
|
||||
@ -126,8 +126,8 @@ public:
|
||||
virtual BYTE* GetStructure();
|
||||
virtual BYTE* GetLinks(int nPageIndex);
|
||||
|
||||
bool MergePages(BYTE* data, DWORD length);
|
||||
bool ValidMetaData();
|
||||
bool MergePages(BYTE* data, DWORD length);
|
||||
int GetRotate(int nPageIndex);
|
||||
int GetMaxRefID();
|
||||
BYTE* GetWidgets();
|
||||
|
||||
@ -961,13 +961,13 @@ BYTE* CPdfReader::GetStructure()
|
||||
for (int iPDF = 0; iPDF < m_vPDFContext.size(); ++iPDF)
|
||||
{
|
||||
PDFDoc* pDoc = m_vPDFContext[iPDF]->m_pDocument;
|
||||
if (!pDoc->getOutline())
|
||||
Outline* pOutline = pDoc->getOutline();
|
||||
if (!pOutline)
|
||||
{
|
||||
nStartPage += pDoc->getNumPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
Outline* pOutline = pDoc->getOutline();
|
||||
GList* pList = pOutline->getItems();
|
||||
if (!pList)
|
||||
{
|
||||
|
||||
@ -30,20 +30,19 @@
|
||||
*
|
||||
*/
|
||||
#include "Destination.h"
|
||||
#include "Pages.h"
|
||||
|
||||
namespace PdfWriter
|
||||
{
|
||||
//----------------------------------------------------------------------------------------
|
||||
// CDestination
|
||||
//----------------------------------------------------------------------------------------
|
||||
CDestination::CDestination(CPage* pPage, CXref* pXref, bool bInline)
|
||||
CDestination::CDestination(CObjectBase* pPage, CXref* pXref, bool bInline)
|
||||
{
|
||||
if (!bInline)
|
||||
pXref->Add(this);
|
||||
|
||||
// Первый элемент массива должен быть страницей, которой принадлежит объект
|
||||
Add((CObjectBase*)pPage);
|
||||
Add(pPage);
|
||||
Add("Fit"); // Значение по умолчанию Fit
|
||||
}
|
||||
bool CDestination::IsValid() const
|
||||
@ -51,21 +50,28 @@ namespace PdfWriter
|
||||
if (m_arrList.size() < 2)
|
||||
return false;
|
||||
|
||||
CObjectBase* pObject = Get(0, false);
|
||||
if ((object_type_DICT != pObject->GetType() || dict_type_PAGE != ((CDictObject*)pObject)->GetDictType()) &&
|
||||
(object_type_PROXY != pObject->GetType() || object_type_DICT != ((CProxyObject*)pObject)->Get()->GetType() || dict_type_PAGE != ((CDictObject*)((CProxyObject*)pObject)->Get())->GetDictType()))
|
||||
return false;
|
||||
// Проверка, что объект является страницей. Но это может быть ссылка на нередактируемую страницу
|
||||
// CObjectBase* pObject = Get(0, false);
|
||||
// if ((object_type_DICT != pObject->GetType() || dict_type_PAGE != ((CDictObject*)pObject)->GetDictType()) &&
|
||||
// (object_type_PROXY != pObject->GetType() || object_type_DICT != ((CProxyObject*)pObject)->Get()->GetType() || dict_type_PAGE != ((CDictObject*)((CProxyObject*)pObject)->Get())->GetDictType()))
|
||||
// return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void CDestination::PrepareArray()
|
||||
{
|
||||
CPage* pPage = (CPage*)Get(0);
|
||||
|
||||
if (m_arrList.size() > 1)
|
||||
{
|
||||
CObjectBase* pPage = Get(0);
|
||||
if (pPage->GetType() != object_type_DICT)
|
||||
{
|
||||
CObjectBase* pCopy = pPage->Copy();
|
||||
pCopy->SetRef(pPage->GetObjId(), pPage->GetGenNo());
|
||||
pPage = new CProxyObject(pCopy, true);
|
||||
}
|
||||
|
||||
Clear();
|
||||
Add((CObjectBase*)pPage);
|
||||
Add(pPage);
|
||||
}
|
||||
}
|
||||
void CDestination::SetXYZ(float fLeft, float fTop, float fZoom)
|
||||
|
||||
@ -36,12 +36,10 @@
|
||||
|
||||
namespace PdfWriter
|
||||
{
|
||||
class CPage;
|
||||
|
||||
class CDestination : public CArrayObject
|
||||
{
|
||||
public:
|
||||
CDestination(CPage* pPage, CXref* pXref, bool bInline = false);
|
||||
CDestination(CObjectBase* pPage, CXref* pXref, bool bInline = false);
|
||||
bool IsValid() const;
|
||||
void SetXYZ (float fLeft, float fTop, float fZoom);
|
||||
void SetFit ();
|
||||
|
||||
@ -527,7 +527,7 @@ namespace PdfWriter
|
||||
|
||||
return new COutline(pParent, sTitle, m_pXref);
|
||||
}
|
||||
CDestination* CDocument::CreateDestination(CPage* pPage, bool bInline)
|
||||
CDestination* CDocument::CreateDestination(CObjectBase* pPage, bool bInline)
|
||||
{
|
||||
if (pPage)
|
||||
return new CDestination(pPage, m_pXref, bInline);
|
||||
|
||||
@ -130,7 +130,8 @@ namespace PdfWriter
|
||||
void AddPageLabel(EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix);
|
||||
void AddPageLabel(unsigned int unPageIndex, EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix);
|
||||
COutline* CreateOutline(COutline* pParent, const char* sTitle);
|
||||
CDestination* CreateDestination(CPage* pPage, bool bInline = false);
|
||||
COutline* GetOutlines() { return m_pOutlines; }
|
||||
CDestination* CreateDestination(CObjectBase* pPage, bool bInline = false);
|
||||
bool AddMetaData(const std::wstring& sMetaName, BYTE* pMetaData, DWORD nMetaLength);
|
||||
|
||||
CExtGrState* GetExtGState(double dAlphaStroke = -1, double dAlphaFill = -1, EBlendMode eMode = blendmode_Unknown, int nStrokeAdjustment = -1);
|
||||
|
||||
@ -90,13 +90,13 @@ public:
|
||||
RELEASEOBJECT(oWorker);
|
||||
}
|
||||
|
||||
void LoadFromFile()
|
||||
void LoadFromFile(const std::wstring& _wsSrcFile = L"")
|
||||
{
|
||||
bool bResult = pdfFile->LoadFromFile(wsSrcFile);
|
||||
bool bResult = pdfFile->LoadFromFile(_wsSrcFile.empty() ? wsSrcFile : _wsSrcFile);
|
||||
if (!bResult)
|
||||
{
|
||||
std::wstring wsPassword = L"123456";
|
||||
bResult = pdfFile->LoadFromFile(wsSrcFile, L"", wsPassword, wsPassword);
|
||||
bResult = pdfFile->LoadFromFile(_wsSrcFile.empty() ? wsSrcFile : _wsSrcFile, L"", wsPassword, wsPassword);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(bResult);
|
||||
@ -350,21 +350,39 @@ TEST_F(CPdfFileTest, VerifySign)
|
||||
RELEASEOBJECT(pCertificate);
|
||||
}
|
||||
|
||||
TEST_F(CPdfFileTest, MergePdf)
|
||||
TEST_F(CPdfFileTest, SplitPdf)
|
||||
{
|
||||
GTEST_SKIP();
|
||||
|
||||
LoadFromFile();
|
||||
std::vector<int> arrPages = { 0, 1 };
|
||||
std::vector<int> arrPages = { 0 };
|
||||
BYTE* pFile = pdfFile->SplitPages(arrPages.data(), arrPages.size());
|
||||
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.CloseFile();
|
||||
|
||||
RELEASEARRAYOBJECTS(pFile);
|
||||
}
|
||||
|
||||
TEST_F(CPdfFileTest, MergePdf)
|
||||
{
|
||||
// GTEST_SKIP();
|
||||
|
||||
LoadFromFile();
|
||||
|
||||
ASSERT_TRUE(pdfFile->EditPdf(wsDstFile));
|
||||
|
||||
pdfFile->MergePages(wsDstFile);
|
||||
std::wstring wsSplitFile = NSFile::GetProcessDirectory() + L"/test_split.pdf";
|
||||
pdfFile->MergePages(wsSplitFile);
|
||||
|
||||
pdfFile->Close();
|
||||
|
||||
RELEASEARRAYOBJECTS(pFile);
|
||||
}
|
||||
|
||||
TEST_F(CPdfFileTest, EditPdf)
|
||||
@ -389,7 +407,7 @@ TEST_F(CPdfFileTest, EditPdf)
|
||||
|
||||
TEST_F(CPdfFileTest, EditPdfFromBase64)
|
||||
{
|
||||
// GTEST_SKIP();
|
||||
GTEST_SKIP();
|
||||
|
||||
NSFonts::NSApplicationFontStream::SetGlobalMemoryStorage(NSFonts::NSApplicationFontStream::CreateDefaultGlobalMemoryStorage());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user