diff --git a/DesktopEditor/graphics/commands/DocInfo.cpp b/DesktopEditor/graphics/commands/DocInfo.cpp index 6ebbaf74e8..e82ba62bfd 100644 --- a/DesktopEditor/graphics/commands/DocInfo.cpp +++ b/DesktopEditor/graphics/commands/DocInfo.cpp @@ -129,9 +129,25 @@ bool CDocInfoCommand::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMeta return true; } -CShapeStart::CShapeStart() : IAdvancedCommand(AdvancedCommandType::ShapeStart) {} +CShapeStart::CShapeStart() : IAdvancedCommand(AdvancedCommandType::ShapeStart) +{ + m_pImage = NULL; +} +CShapeStart::~CShapeStart() +{ + RELEASEINTERFACE(m_pImage); +} void CShapeStart::SetShapeXML(const std::string& sShapeXML) { m_sShapeXML = sShapeXML; } +void CShapeStart::SetShapeImage(BYTE* pImgData, int nWidth, int nHeight) +{ + if (pImgData) + { + m_pImage = new Aggplus::CImage(); + m_pImage->Create(pImgData, nWidth, nHeight, -4 * nWidth); + } +} const std::string& CShapeStart::GetShapeXML() { return m_sShapeXML; } +Aggplus::CImage* CShapeStart::GetShapeImage() { return m_pImage; } bool CShapeStart::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRenderter* pCorrector) { m_sShapeXML = pReader->ReadStringA(); diff --git a/DesktopEditor/graphics/commands/DocInfo.h b/DesktopEditor/graphics/commands/DocInfo.h index 9690ffd14f..f17ed97b33 100644 --- a/DesktopEditor/graphics/commands/DocInfo.h +++ b/DesktopEditor/graphics/commands/DocInfo.h @@ -136,14 +136,19 @@ class GRAPHICS_DECL CShapeStart : public IAdvancedCommand { public: CShapeStart(); + ~CShapeStart(); + + const std::string& GetShapeXML(); + Aggplus::CImage* GetShapeImage(); void SetShapeXML(const std::string& sShapeXML); - const std::string& GetShapeXML(); + void SetShapeImage(BYTE* pImgData, int nWidth, int nHeight); bool Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRenderter* pCorrector); private: std::string m_sShapeXML; + Aggplus::CImage* m_pImage; }; class GRAPHICS_DECL CEmptyComand : public IAdvancedCommand diff --git a/PdfFile/PdfEditor.cpp b/PdfFile/PdfEditor.cpp index aeb5a9673e..909f6f5bd0 100644 --- a/PdfFile/PdfEditor.cpp +++ b/PdfFile/PdfEditor.cpp @@ -1288,7 +1288,7 @@ void CPdfEditor::AddShapeXML(const std::string& sXML) } void CPdfEditor::EndMarkedContent() { - pWriter->GetPage()->EndMarkedContent(); + pWriter->GetDocument()->EndShapeXML(); } bool CPdfEditor::IsBase14(const std::wstring& wsFontName, bool& bBold, bool& bItalic, std::wstring& wsFontPath) { diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index f56cdedddd..283f444e48 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1656,7 +1656,7 @@ BYTE* CPdfReader::GetShapes(int nPageIndex) Object oProperties, oMetaOForm, oID; XRef* xref = m_pPDFDocument->getXRef(); - if (!pResources->lookup("Properties", &oProperties)->isDict() || !oProperties.dictLookup("MetaOForm", &oMetaOForm)->isDict("MetaOForm") || !oMetaOForm.dictLookup("ID", &oID)->isString()) + if (!pResources->lookup("Properties", &oProperties)->isDict() || !oProperties.dictLookup("OShapes", &oMetaOForm)->isDict("OShapes") || !oMetaOForm.dictLookup("ID", &oID)->isString()) { oProperties.free(); oMetaOForm.free(); oID.free(); return NULL; diff --git a/PdfFile/SrcReader/RendererOutputDev.cpp b/PdfFile/SrcReader/RendererOutputDev.cpp index 29ebe5029b..4b5c6cdd20 100644 --- a/PdfFile/SrcReader/RendererOutputDev.cpp +++ b/PdfFile/SrcReader/RendererOutputDev.cpp @@ -4195,12 +4195,47 @@ namespace PdfReader return; } GBool RendererOutputDev::beginMarkedContent(GfxState *state, GString* s) + { + return gFalse; + } + GBool RendererOutputDev::beginMCOShapes(GfxState *state, GString *s, Object *ref) { IAdvancedCommand::AdvancedCommandType eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::ShapeStart; if (m_pRenderer->IsSupportAdvancedCommand(eAdvancedCommandType) == S_OK) { CShapeStart* pCommand = new CShapeStart(); pCommand->SetShapeXML(s->getCString()); + + Object oIm; + if (ref && ref->isRef() && ref->fetch(m_pXref, &oIm)->isStream()) + { + Dict *oImDict = oIm.streamGetDict(); + + int nLength = 0; + Object oLength; + if (oImDict->lookup("Length", &oLength)->isInt()) + nLength = oLength.getInt(); + oLength.free(); + if (oImDict->lookup("DL", &oLength)->isInt()) + nLength = oLength.getInt(); + oLength.free(); + + Stream* pImage = oIm.getStream()->getUndecodedStream(); + pImage->reset(); + + BYTE* pBuffer = new BYTE[nLength]; + BYTE* pBufferPtr = pBuffer; + for (int nI = 0; nI < nLength; ++nI) + *pBufferPtr++ = (BYTE)pImage->getChar(); + + CBgraFrame oFrame; + if (oFrame.Decode(pBuffer, nLength)) + { + pCommand->SetShapeImage(oFrame.get_Data(), oFrame.get_Width(), oFrame.get_Height()); + oFrame.ClearNoAttack(); + } + } + oIm.free(); bool bRes = m_pRenderer->AdvancedCommand(pCommand) == S_OK; RELEASEOBJECT(pCommand); if (bRes) diff --git a/PdfFile/SrcReader/RendererOutputDev.h b/PdfFile/SrcReader/RendererOutputDev.h index 24b698b15f..b8fa2c3d0f 100644 --- a/PdfFile/SrcReader/RendererOutputDev.h +++ b/PdfFile/SrcReader/RendererOutputDev.h @@ -260,6 +260,7 @@ namespace PdfReader void Type3D1(GfxState *pGState, double dWx, double dWy, double dBLx, double dBLy, double dTRx, double dTRy); //----- Дополнительные функции virtual GBool beginMarkedContent(GfxState *state, GString *s) override; + virtual GBool beginMCOShapes(GfxState *state, GString *s, Object *ref) override; virtual void endMarkedContent(GfxState *state) override; //----- Вывод картинок virtual void drawImageMask(GfxState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GBool bInvert, GBool bInlineImage, GBool interpolate) override; diff --git a/PdfFile/SrcWriter/Document.cpp b/PdfFile/SrcWriter/Document.cpp index 08b1091e13..c49b098da1 100644 --- a/PdfFile/SrcWriter/Document.cpp +++ b/PdfFile/SrcWriter/Document.cpp @@ -80,6 +80,7 @@ namespace PdfWriter m_pPageTree = NULL; m_pCurPage = NULL; m_nCurPageNum = -1; + m_pCurImage = NULL; m_unFormFields = 0; m_pInfo = NULL; m_pTrailer = NULL; @@ -192,6 +193,7 @@ namespace PdfWriter m_pPageTree = NULL; m_pCurPage = NULL; m_nCurPageNum = 0; + m_pCurImage = NULL; m_unFormFields = 0; m_bEncrypt = false; m_pEncryptDict = NULL; @@ -1271,7 +1273,10 @@ namespace PdfWriter for (size_t i = 0, nSize = m_vImages.size(); i < nSize; ++i) { if (m_vImages[i].wsImagePath == wsImagePath && m_vImages[i].nAlpha == nAlpha) + { + m_pCurImage = m_vImages[i].pImage; return m_vImages[i].pImage; + } } return NULL; } @@ -1279,6 +1284,7 @@ namespace PdfWriter { if (!pImage) return; + m_pCurImage = pImage; m_vImages.push_back({wsImagePath, nAlpha, pImage}); } bool CDocument::CheckFieldName(CFieldBase* pField, const std::string& sName) @@ -1782,10 +1788,10 @@ namespace PdfWriter pProperties = new CDictObject(); pResources->Add("Properties", pProperties); } - CObjectBase* pObj = pProperties->Get("MetaOForm"); + CObjectBase* pObj = pProperties->Get("OShapes"); if (pObj && pObj->GetType() != object_type_DICT) { - pProperties->Remove("MetaOForm"); + pProperties->Remove("OShapes"); pObj = NULL; } CDictObject* pMetaOForm = (CDictObject*)pObj; @@ -1793,8 +1799,8 @@ namespace PdfWriter { pMetaOForm = new CDictObject(); m_pXref->Add(pMetaOForm); - pMetaOForm->Add("Type", "MetaOForm"); - pProperties->Add("MetaOForm", pMetaOForm); + pMetaOForm->Add("Type", "OShapes"); + pProperties->Add("OShapes", pMetaOForm); m_vMetaOForms.push_back(pMetaOForm); CBinaryObject* sID = NULL; @@ -1821,14 +1827,39 @@ namespace PdfWriter { pArrayMeta = new CArrayObject(); pMetaOForm->Add("Metadata", pArrayMeta); + CArrayObject* pArrayImage = new CArrayObject(); + pMetaOForm->Add("Image", pArrayImage); } pArrayMeta->Add(new CStringObject(sXML.c_str())); CDictObject* pBDC = new CDictObject(); pBDC->Add("MCID", pArrayMeta->GetCount() - 1); - m_pCurPage->BeginMarkedContentDict("MetaOForm", pBDC); + m_pCurPage->BeginMarkedContentDict("OShapes", pBDC); RELEASEOBJECT(pBDC); } + void CDocument::EndShapeXML() + { + CDictObject* pResources = (CDictObject*)m_pCurPage->Get("Resources"); + if (!pResources) + return; + CDictObject* pProperties = (CDictObject*)pResources->Get("Properties"); + if (!pProperties) + return; + CObjectBase* pObj = pProperties->Get("OShapes"); + if (!pObj || pObj->GetType() != object_type_DICT) + return; + CDictObject* pMetaOForm = (CDictObject*)pObj; + CArrayObject* pArrayImage = (CArrayObject*)pMetaOForm->Get("Image"); + if (!pArrayImage) + return; + + pObj = m_pCurImage; + if (!pObj) + pObj = new PdfWriter::CNullObject(); + pArrayImage->Add(pObj); + + m_pCurPage->EndMarkedContent(); + } void CDocument::ClearPage() { m_pCurPage->ClearContent(m_pXref); diff --git a/PdfFile/SrcWriter/Document.h b/PdfFile/SrcWriter/Document.h index 6d12ee0fc7..a9553518ec 100644 --- a/PdfFile/SrcWriter/Document.h +++ b/PdfFile/SrcWriter/Document.h @@ -183,6 +183,8 @@ namespace PdfWriter bool HasImage(const std::wstring& wsImagePath, BYTE nAlpha); CImageDict* GetImage(const std::wstring& wsImagePath, BYTE nAlpha); void AddImage(const std::wstring& wsImagePath, BYTE nAlpha, CImageDict* pImage); + CImageDict* GetCurImage() { return m_pCurImage; } + void SetCurImage(CImageDict* pImage) { m_pCurImage = pImage; } bool CreatePageTree(CXref* pXref, CPageTree* pPageTree); bool EditPdf(const std::wstring& wsPath, int nPosLastXRef, int nSizeXRef, CXref* pXref, CCatalog* pCatalog, CEncryptDict* pEncrypt, int nFormField); @@ -205,6 +207,7 @@ namespace PdfWriter bool EditCO(const std::vector& arrCO); const std::map& GetAnnots() { return m_mAnnotations; } void AddShapeXML(const std::string& sXML); + void EndShapeXML(); void ClearPage(); private: @@ -274,6 +277,7 @@ namespace PdfWriter CPageTree* m_pPageTree; CPage* m_pCurPage; int m_nCurPageNum; + CImageDict* m_pCurImage; CInfoDict* m_pInfo; CDictObject* m_pTrailer; CDictObject* m_pResources; diff --git a/PdfFile/lib/xpdf/Gfx.cc b/PdfFile/lib/xpdf/Gfx.cc index 8879323061..4a66ee81a3 100644 --- a/PdfFile/lib/xpdf/Gfx.cc +++ b/PdfFile/lib/xpdf/Gfx.cc @@ -5053,21 +5053,27 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { mcKind = gfxMCActualText; } obj.free(); - } else if (args[0].isName("MetaOForm") && numArgs == 2 && args[1].isDict() && res->lookupPropertiesNF("MetaOForm", &obj)) { + } else if (args[0].isName("OShapes") && numArgs == 2 && args[1].isDict() && res->lookupPropertiesNF("OShapes", &obj)) { Object oMetaOForm, oID, oTID, oID2, oMCID, oMetadata, oMetadataCur; - if (obj.fetch(xref, &oMetaOForm)->isDict("MetaOForm") && oMetaOForm.dictLookup("ID", &oID)->isString() && xref->getTrailerDict()->dictLookup("ID", &oTID)->isArray() && + if (obj.fetch(xref, &oMetaOForm)->isDict("OShapes") && oMetaOForm.dictLookup("ID", &oID)->isString() && xref->getTrailerDict()->dictLookup("ID", &oTID)->isArray() && oTID.arrayGet(1, &oID2)->isString() && oID2.getString()->cmp(oID.getString()) == 0 && args[1].dictLookup("MCID", &oMCID)->isInt() && - oMetaOForm.dictLookup("Metadata", &oMetadata)->isArray() && oMetadata.arrayGet(oMCID.getInt(), &oMetadataCur)->isString() && - out->beginMarkedContent(state, oMetadataCur.getString())) { - oMetaOForm.free(); oID.free(); oTID.free(); oID2.free(); oMCID.free(), oMetadata.free(); oMetadataCur.free(); obj.free(); - getContentObj(&obj); - while (!obj.isEOF() && !obj.isCmd("EMC")) { - obj.free(); + oMetaOForm.dictLookup("Metadata", &oMetadata)->isArray() && oMetadata.arrayGet(oMCID.getInt(), &oMetadataCur)->isString()) { + oID.free(); oTID.free(); oID2.free(); oMCID.free(); oMetadata.free(); obj.free(); + Object oImRef, oArrImage; + if (!oMetaOForm.dictLookup("Image", &oArrImage)->isArray() || !oArrImage.arrayGetNF(oMCID.getInt(), &oImRef)->isRef()) + oImRef.free(); + if (out->beginMCOShapes(state, oMetadataCur.getString(), &oImRef)) { getContentObj(&obj); + while (!obj.isEOF() && !obj.isCmd("EMC")) { + obj.free(); + getContentObj(&obj); + } + out->endMarkedContent(state); + oImRef.free(); oArrImage.free(); + oMetaOForm.free(); oMetadataCur.free(); obj.free(); + return; } - obj.free(); - out->endMarkedContent(state); - return; + oImRef.free(); oArrImage.free(); } oMetaOForm.free(); oID.free(); oTID.free(); oID2.free(); oMCID.free(), oMetadata.free(); oMetadataCur.free(); obj.free(); } diff --git a/PdfFile/lib/xpdf/OutputDev.h b/PdfFile/lib/xpdf/OutputDev.h index a770dfd6ff..540c290071 100644 --- a/PdfFile/lib/xpdf/OutputDev.h +++ b/PdfFile/lib/xpdf/OutputDev.h @@ -188,6 +188,7 @@ public: //----- additional virtual GBool beginMarkedContent(GfxState *state, GString *s) { return gFalse; } + virtual GBool beginMCOShapes(GfxState *state, GString *s, Object *ref) { return gFalse; } virtual void endMarkedContent(GfxState *state) {} //----- image drawing