diff --git a/PdfFile/PdfEditor.cpp b/PdfFile/PdfEditor.cpp index 286cb03696..844288193c 100644 --- a/PdfFile/PdfEditor.cpp +++ b/PdfFile/PdfEditor.cpp @@ -416,7 +416,49 @@ PdfWriter::CObjectBase* DictToCDictObject2(Object* obj, PdfWriter::CDocument* pD for (int nIndex = 0; nIndex < obj->dictGetLength(); ++nIndex) { char* chKey = obj->dictGetKey(nIndex); - obj->dictGetValNF(nIndex, &oTemp); + if (strcmp("Resources", chKey) == 0) + { + Ref oResourcesRef = { -1, -1 }; + if (obj->dictGetValNF(nIndex, &oTemp)->isRef()) + oResourcesRef = oTemp.getRef(); + oTemp.free(); + + PdfWriter::CObjectBase* pObj = oResourcesRef.num > 0 ? pManager->GetObj(oResourcesRef.num + nStartRefID) : NULL; + if (pObj) + { + pDict->Add(chKey, pObj); + pManager->IncRefCount(oResourcesRef.num + nStartRefID); + continue; + } + + if (obj->dictGetVal(nIndex, &oTemp)->isDict()) + { + PdfWriter::CResourcesDict* pResDict = pDoc->CreateResourcesDict(oResourcesRef.num < 0, false); + if (oResourcesRef.num > 0) + pManager->AddObj(oResourcesRef.num + nStartRefID, pResDict); + pDict->Add(chKey, pResDict); + for (int nIndex2 = 0; nIndex2 < oTemp.dictGetLength(); ++nIndex2) + { + Object oRes; + char* chKey2 = oTemp.dictGetKey(nIndex2); + oTemp.dictGetValNF(nIndex2, &oRes); + pBase = DictToCDictObject2(&oRes, pDoc, xref, pManager, nStartRefID, 0, bUndecodedStream); + pResDict->Add(chKey2, pBase); + oRes.free(); + } + pResDict->Fix(); + + oTemp.free(); + continue; + } + else + { + oTemp.free(); + obj->dictGetValNF(nIndex, &oTemp); + } + } + else + obj->dictGetValNF(nIndex, &oTemp); pBase = DictToCDictObject2(&oTemp, pDoc, xref, pManager, nStartRefID, 0, bUndecodedStream); pDict->Add(chKey, pBase); oTemp.free(); @@ -470,7 +512,49 @@ PdfWriter::CObjectBase* DictToCDictObject2(Object* obj, PdfWriter::CDocument* pD oTemp.free(); continue; } - pODict->getValNF(nIndex, &oTemp); + else if (strcmp("Resources", chKey) == 0) + { + Ref oResourcesRef = { -1, -1 }; + if (pODict->getValNF(nIndex, &oTemp)->isRef()) + oResourcesRef = oTemp.getRef(); + oTemp.free(); + + PdfWriter::CObjectBase* pObj = oResourcesRef.num > 0 ? pManager->GetObj(oResourcesRef.num + nStartRefID) : NULL; + if (pObj) + { + pDict->Add(chKey, pObj); + pManager->IncRefCount(oResourcesRef.num + nStartRefID); + continue; + } + + if (pODict->getVal(nIndex, &oTemp)->isDict()) + { + PdfWriter::CResourcesDict* pResDict = pDoc->CreateResourcesDict(oResourcesRef.num < 0, false); + if (oResourcesRef.num > 0) + pManager->AddObj(oResourcesRef.num + nStartRefID, pResDict); + pDict->Add(chKey, pResDict); + for (int nIndex2 = 0; nIndex2 < oTemp.dictGetLength(); ++nIndex2) + { + Object oRes; + char* chKey2 = oTemp.dictGetKey(nIndex2); + oTemp.dictGetValNF(nIndex2, &oRes); + pBase = DictToCDictObject2(&oRes, pDoc, xref, pManager, nStartRefID, 0, bUndecodedStream); + pResDict->Add(chKey2, pBase); + oRes.free(); + } + pResDict->Fix(); + + oTemp.free(); + continue; + } + else + { + oTemp.free(); + pODict->getValNF(nIndex, &oTemp); + } + } + else + pODict->getValNF(nIndex, &oTemp); pBase = DictToCDictObject2(&oTemp, pDoc, xref, pManager, nStartRefID); pDict->Add(chKey, pBase); oTemp.free(); @@ -2337,11 +2421,11 @@ bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength, PDFD if (oResourcesRef.num > 0) m_mObjManager.AddObj(oResourcesRef.num + nStartRefID, pDict); pPage->Add(chKey, pDict); - for (int nIndex = 0; nIndex < oTemp.dictGetLength(); ++nIndex) + for (int nIndex2 = 0; nIndex2 < oTemp.dictGetLength(); ++nIndex2) { Object oRes; - char* chKey2 = oTemp.dictGetKey(nIndex); - oTemp.dictGetValNF(nIndex, &oRes); + char* chKey2 = oTemp.dictGetKey(nIndex2); + oTemp.dictGetValNF(nIndex2, &oRes); PdfWriter::CObjectBase* pBase = DictToCDictObject2(&oRes, pDoc, xref, &m_mObjManager, nStartRefID); pDict->Add(chKey2, pBase); oRes.free(); @@ -4051,7 +4135,35 @@ void CPdfEditor::ClearPage() pageObj.free(); if (m_nMode == Mode::Split || m_nMode == Mode::WriteNew) + { + PdfWriter::CPage* pPage = pDoc->GetCurPage(); + auto removeContentObj = [&](PdfWriter::CObjectBase* pObj) + { + if (pObj->GetType() == PdfWriter::object_type_DICT) + { + PdfWriter::CObjectBase* pLength = ((PdfWriter::CDictObject*)pObj)->Get("Length"); + if (pLength) + { + int nLengthID = m_mObjManager.FindObj(pLength); + m_mObjManager.RemoveObj(nLengthID); + } + } + int nObjID = m_mObjManager.FindObj(pObj); + m_mObjManager.RemoveObj(nObjID); + }; + + PdfWriter::CObjectBase* pObjContents = pPage->Get("Contents"); + if (pObjContents && pObjContents->GetType() == PdfWriter::object_type_ARRAY) + { + PdfWriter::CArrayObject* pContents = (PdfWriter::CArrayObject*)pObjContents; + for (int i = 0; i < pContents->GetCount(); ++i) + removeContentObj(pContents->Get(i)); + } + else if (pObjContents) + removeContentObj(pObjContents); + pDoc->ClearPageFull(); + } else pDoc->ClearPage(); diff --git a/PdfFile/SrcWriter/RedactOutputDev.cpp b/PdfFile/SrcWriter/RedactOutputDev.cpp index bf1eb4f432..89d7efba42 100644 --- a/PdfFile/SrcWriter/RedactOutputDev.cpp +++ b/PdfFile/SrcWriter/RedactOutputDev.cpp @@ -521,6 +521,7 @@ void ApplyRedactToGray(const std::vector& arrQuadPoints, BYTE* pImage, i RedactOutputDev::RedactOutputDev(CPdfWriter* pRenderer, CObjectsManager* pObjMng, int nStartRefID) { m_pXref = NULL; + m_pResources = NULL; m_pRenderer = pRenderer; m_mObjManager = pObjMng; @@ -565,6 +566,32 @@ void RedactOutputDev::startPage(int nPageIndex, GfxState *pGState) m_pPage = m_pDoc->GetEditPage(nPageIndex); m_pRenderer->EditPage(m_pPage); m_pDoc->SetCurPage(m_pPage); + + auto removeContentObj = [&](PdfWriter::CObjectBase* pObj) + { + if (pObj->GetType() == PdfWriter::object_type_DICT) + { + PdfWriter::CObjectBase* pLength = ((PdfWriter::CDictObject*)pObj)->Get("Length"); + if (pLength) + { + int nLengthID = m_mObjManager->FindObj(pLength); + m_mObjManager->RemoveObj(nLengthID); + } + } + int nObjID = m_mObjManager->FindObj(pObj); + m_mObjManager->RemoveObj(nObjID); + }; + + PdfWriter::CObjectBase* pObjContents = m_pPage->Get("Contents"); + if (pObjContents && pObjContents->GetType() == PdfWriter::object_type_ARRAY) + { + PdfWriter::CArrayObject* pContents = (PdfWriter::CArrayObject*)pObjContents; + for (int i = 0; i < pContents->GetCount(); ++i) + removeContentObj(pContents->Get(i)); + } + else if (pObjContents) + removeContentObj(pObjContents); + m_pDoc->ClearPageFull(); } void RedactOutputDev::endPage() @@ -1374,11 +1401,16 @@ void RedactOutputDev::drawForm(GfxState *pGState, Gfx *gfx, Ref id, const char* pObj = pOrigForm->Get("Matrix"); if (pObj) pNewForm->Add("Matrix", pObj->Copy()); + + PdfWriter::CResourcesDict* pNewResources = NULL; pObj = pOrigForm->Get("Resources"); if (pObj) + { pNewForm->Add("Resources", pObj->Copy()); + pNewResources = dynamic_cast(pNewForm->Get("Resources")); + } - PdfWriter::CResourcesDict* pResources = GetResources(gfx); + PdfWriter::CResourcesDict* pResources = GetResources(gfx, pNewForm); if (pResources) name = pResources->GetXObjectName(pNewForm); @@ -1391,6 +1423,7 @@ void RedactOutputDev::drawForm(GfxState *pGState, Gfx *gfx, Ref id, const char* RedactOutputDev* pFormOutputDev = new RedactOutputDev(m_pRenderer, m_mObjManager, m_nStartRefID); pFormOutputDev->NewPDF(m_pXref); pFormOutputDev->m_pPage = pFakePage; + pFormOutputDev->m_pResources = pNewResources; std::vector arrFormQuadPoints; double dInvMatrix[6] = { 1, 0, 0, 1, 0, 0 }; InvertMatrix(m_arrMatrix, dInvMatrix); @@ -1886,8 +1919,11 @@ CObjectBase* RedactOutputDev::CreateImage(Gfx *gfx, int nWidth, int nHeight, uns return pObj; } -CResourcesDict* RedactOutputDev::GetResources(Gfx *gfx) +CResourcesDict* RedactOutputDev::GetResources(Gfx *gfx, CDictObject* pNewForm) { + if (m_pResources) + return m_pResources; + PdfWriter::CResourcesDict* pResources = NULL; Object* pContent = gfx->getTopContentStreamStack(); if (pContent && pContent->isRef()) @@ -1901,7 +1937,7 @@ CResourcesDict* RedactOutputDev::GetResources(Gfx *gfx) if (!pResources) { pResources = new PdfWriter::CResourcesDict(NULL, true, false); - pDictForm->Add("Resources", pResources); + (pNewForm ? pNewForm : pDictForm)->Add("Resources", pResources); } } } diff --git a/PdfFile/SrcWriter/RedactOutputDev.h b/PdfFile/SrcWriter/RedactOutputDev.h index d6c7e8724c..d5636beb34 100644 --- a/PdfFile/SrcWriter/RedactOutputDev.h +++ b/PdfFile/SrcWriter/RedactOutputDev.h @@ -201,11 +201,12 @@ namespace PdfWriter void DoStateOp(); void DrawXObject(const char* name); CObjectBase* CreateImage(Gfx *gfx, int nWidth, int nHeight, unsigned int nFilter, int nBPC, const char* sCS); - CResourcesDict* GetResources(Gfx *gfx); + CResourcesDict* GetResources(Gfx *gfx, CDictObject* pNewForm); XRef* m_pXref; std::vector m_arrQuadPoints; Aggplus::CGraphicsPath m_oPathRedact; + CResourcesDict* m_pResources; CPdfWriter* m_pRenderer; CObjectsManager* m_mObjManager; diff --git a/PdfFile/SrcWriter/ResourcesDictionary.cpp b/PdfFile/SrcWriter/ResourcesDictionary.cpp index fd74076ca5..3a6de8595f 100644 --- a/PdfFile/SrcWriter/ResourcesDictionary.cpp +++ b/PdfFile/SrcWriter/ResourcesDictionary.cpp @@ -67,6 +67,19 @@ namespace PdfWriter pProcset->Add(new CNameObject("ImageI")); } } + CObjectBase* CResourcesDict::Copy(CObjectBase* pOut) const + { + CResourcesDict* pDict = pOut && pOut->GetType() == object_type_DICT ? dynamic_cast(pOut) : new CResourcesDict(NULL, true, false); + if (!pDict) + return NULL; + + for (auto const &oIter : m_mList) + pDict->Add(oIter.first, oIter.second->Copy()); + + pDict->Fix(); + + return pDict; + } const char* CResourcesDict::GetFontName(CFontDict* pFont) { if (!m_pFonts) diff --git a/PdfFile/SrcWriter/ResourcesDictionary.h b/PdfFile/SrcWriter/ResourcesDictionary.h index 47eb1d074d..f9e7d98613 100644 --- a/PdfFile/SrcWriter/ResourcesDictionary.h +++ b/PdfFile/SrcWriter/ResourcesDictionary.h @@ -46,6 +46,8 @@ namespace PdfWriter public: CResourcesDict(CXref* pXref, bool bInline, bool bProcSet); + virtual CObjectBase* Copy(CObjectBase* pOut) const override; + const char* GetFontName(CFontDict* pFont); const char* GetExtGrStateName(CExtGrState* pState); const char* GetXObjectName(CObjectBase* pXObject);