From 29cee43448afd2b4858b928d11d8568635031ab2 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Tue, 1 Jul 2025 10:46:38 +0300 Subject: [PATCH 01/19] Add split mode for PdfWriter --- PdfFile/PdfFile.cpp | 2 ++ PdfFile/PdfWriter.cpp | 25 +++++++++++++++++-------- PdfFile/PdfWriter.h | 2 ++ PdfFile/SrcWriter/Annotation.cpp | 6 ++++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index d8993c2d2e..abd3bfbc5d 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -452,8 +452,10 @@ BYTE* CPdfFile::SplitPages(const int* arrPageIndex, unsigned int unLength, BYTE* { if (pChanges && nLength > 3) { + m_pInternal->pWriter->SetSplit(true); CConvertFromBinParams* pParams = new CConvertFromBinParams(); AddToPdfFromBinary(pChanges + 4, nLength - 4, pParams); + m_pInternal->pWriter->SetSplit(false); } m_pInternal->pEditor->AfterSplitPages(); diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index cb1746949b..872bdd9a02 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -161,6 +161,7 @@ CPdfWriter::CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA, IRend m_pDocument->SetCompressionMode(COMP_ALL); m_bValid = true; + m_bSplit = false; m_dPageHeight = 297; m_dPageWidth = 210; m_pPage = NULL; @@ -2067,7 +2068,6 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF pLineAnnot->SetCO(dCO1, dCO2); } - //pLineAnnot->SetAP(); if (bRender) { pMarkupAnnot->RemoveAP(); @@ -2187,8 +2187,6 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } if (nFlags & (1 << 16)) pCaretAnnot->SetSy(pPr->GetSy()); - - // pMarkupAnnot->RemoveAP(); } else if (oInfo.IsStamp()) { @@ -2354,19 +2352,19 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (nFlags & (1 << 10)) { pButtonWidget->SetCA(pPr->GetCA()); - if (nTP == 0) + if (nTP == 0 && !m_bSplit) DrawButtonWidget(pAppFonts, pButtonWidget, 0, NULL); } if (nFlags & (1 << 11)) { pButtonWidget->SetRC(pPr->GetRC()); - if (nTP == 0) + if (nTP == 0 && !m_bSplit) DrawButtonWidget(pAppFonts, pButtonWidget, 1, NULL); } if (nFlags & (1 << 12)) { pButtonWidget->SetAC(pPr->GetAC()); - if (nTP == 0) + if (nTP == 0 && !m_bSplit) DrawButtonWidget(pAppFonts, pButtonWidget, 2, NULL); } } @@ -2475,7 +2473,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (pFont) pWidgetAnnot->SetDA(pFont, oInfo.GetWidgetAnnotPr()->GetFontSize(), dFontSize, oInfo.GetWidgetAnnotPr()->GetTC()); } - else if ((bValue && pTextWidget->Get("T")) || bAPValue) + else if (!m_bSplit && ((bValue && pTextWidget->Get("T")) || bAPValue)) { put_FontName(wsFontName); put_FontStyle(nStyle); @@ -2542,7 +2540,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (pFont) pWidgetAnnot->SetDA(pFont, oInfo.GetWidgetAnnotPr()->GetFontSize(), dFontSize, oInfo.GetWidgetAnnotPr()->GetTC()); } - else if (!arrValue.empty()) + else if (!m_bSplit && !arrValue.empty()) { put_FontName(wsFontName); put_FontStyle(nStyle); @@ -2904,6 +2902,9 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi std::vector arrForm; for (int i = 0; i < arrBI.size(); ++i) { + if (m_bSplit) + break; + std::wstring wsPath = arrBI[i]; if (wsPath.empty()) { @@ -2923,6 +2924,9 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi std::map mAnnots = m_pDocument->GetAnnots(); for (auto it = mAnnots.begin(); it != mAnnots.end(); it++) { + if (m_bSplit) + break; + PdfWriter::CAnnotation* pAnnot = it->second; if (pAnnot->GetAnnotationType() != PdfWriter::AnnotWidget) continue; @@ -3301,6 +3305,8 @@ bool CPdfWriter::GetBaseFont14(const std::wstring& wsFontName, int nBase14) if (!FindFontPath(wsFontName, m_oFont.IsBold(), m_oFont.IsItalic(), wsFontPath, lFaceIndex)) return false; } + if (m_bSplit) + return false; if (!m_pFontManager->LoadFontFromFile(wsFontPath, lFaceIndex, m_oFont.GetSize(), 72, 72)) return false; PdfWriter::EStandard14Fonts nType = (PdfWriter::EStandard14Fonts)nBase14; @@ -3412,6 +3418,9 @@ PdfWriter::CFontCidTrueType* CPdfWriter::GetFont(const std::wstring& wsFontPath, if (pFont) return pFont; + if (m_bSplit) + return pFont; + // TODO: Пока мы здесь предполагаем, что шрифты только либо TrueType, либо OpenType if (!m_pFontManager->LoadFontFromFile(wsFontPath, lFaceIndex, 10, 72, 72)) { diff --git a/PdfFile/PdfWriter.h b/PdfFile/PdfWriter.h index 9c982d4120..c27a7ed9ae 100644 --- a/PdfFile/PdfWriter.h +++ b/PdfFile/PdfWriter.h @@ -222,6 +222,7 @@ public: void AddFont(const std::wstring& wsFontName, const bool& bBold, const bool& bItalic, const std::wstring& wsFontPath, const LONG& lFaceIndex); void SetHeadings(CHeadings* pCommand); void SetNeedAddHelvetica(bool bNeedAddHelvetica); + void SetSplit(bool bSplit) { m_bSplit = bSplit; } private: PdfWriter::CImageDict* LoadImage(Aggplus::CImage* pImage, BYTE nAlpha); @@ -284,6 +285,7 @@ private: CMultiLineTextManager m_oLinesManager; bool m_bValid; + bool m_bSplit; }; #endif // _PDF_WRITER_H diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index 03baa7468a..1e05de8751 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -823,6 +823,9 @@ namespace PdfWriter } void CFreeTextAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const std::vector& arrC) { + if (!pFont) + return; + CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources(); const char* sFontName = pFieldsResources->GetFontName(pFont); @@ -1229,6 +1232,9 @@ namespace PdfWriter } void CWidgetAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const double& dFontSizeAP, const std::vector& arrTC) { + if (!pFont) + return; + CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources(); const char* sFontName = pFieldsResources->GetFontName(pFont); From 6c2a8205ecd90daad5c90ab4f142bfb8954a8e76 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Tue, 1 Jul 2025 11:07:39 +0300 Subject: [PATCH 02/19] Fix m_bSplit --- PdfFile/PdfWriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 872bdd9a02..007d07549d 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -2722,7 +2722,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi if (nType == PdfWriter::WidgetCombobox || nType == PdfWriter::WidgetListbox) { PdfWriter::CChoiceWidget* pKid = dynamic_cast(pObj); - if (!pKid->HaveAPV()) + if (!pKid->HaveAPV() && !m_bSplit) DrawChoiceWidget(pAppFonts, pKid, pParent->arrV); } } @@ -2854,13 +2854,13 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi if (nType == PdfWriter::WidgetCombobox || nType == PdfWriter::WidgetListbox) { PdfWriter::CChoiceWidget* pKid = dynamic_cast(pObj); - if (!pKid->HaveAPV()) + if (!pKid->HaveAPV() && !m_bSplit) DrawChoiceWidget(pAppFonts, pKid, {pParent->sV}); } else if (nType == PdfWriter::WidgetText) { PdfWriter::CTextWidget* pKid = dynamic_cast(pObj); - if (!pKid->HaveAPV()) + if (!pKid->HaveAPV() && !m_bSplit) DrawTextWidget(pAppFonts, pKid, pParent->sV); } } From 0715c0c5a5308bac7436c3ff4098082630050bf4 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 4 Jul 2025 10:53:00 +0300 Subject: [PATCH 03/19] Fix merge prefix name --- PdfFile/PdfReader.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 754d2e30be..8a24f2aec2 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1200,6 +1200,13 @@ BYTE* CPdfReader::GetWidgets() const std::vector& arrAnnots = pAnnots->GetAnnots(); for (int i = 0; i < arrAnnots.size(); ++i) { + if (m_vPDFContext[iPDF]->m_sPrefixForm.empty()) + continue; + + std::string sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm; + pAnnots->ChangeFullNameAnnot(i, sPrefix); + + /* const std::string& sFullName = arrAnnots[i]->GetFullName(); std::map::iterator it = mForms.find(sFullName); if (it == mForms.end()) @@ -1214,11 +1221,13 @@ BYTE* CPdfReader::GetWidgets() else { int nPrefix = 0; - std::string sPrefix = m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(nPrefix); + std::string sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(nPrefix); + pAnnots->ChangeFullNameAnnot(i, sPrefix); while (!pAnnots->ChangeFullNameAnnot(i, sPrefix)) - sPrefix = m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(++nPrefix); + sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(++nPrefix); } } + */ } pAnnots->ToWASM(oRes); From fbed837a4745a9c58f47db5c58f579932f3cb2ac Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 4 Jul 2025 10:59:33 +0300 Subject: [PATCH 04/19] Fix change parrent FullName --- Common/js/__pycache__/common.cpython-310.pyc | Bin 0 -> 783 bytes PdfFile/SrcReader/PdfAnnot.cpp | 4 ++++ PdfFile/SrcReader/PdfAnnot.h | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 Common/js/__pycache__/common.cpython-310.pyc diff --git a/Common/js/__pycache__/common.cpython-310.pyc b/Common/js/__pycache__/common.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8dcf0ac0dba654b0d5694e0b1be9e1e219b1974 GIT binary patch literal 783 zcmZ8f%W4}j6xC}UaqN;7L+GZ9E()`8XuByT4FwZJpg4=JY7E0zQi+2+Ge{F!oAIvw z56`l{q+RJMl>R_hy^`V(dS`TX?n}ByQZ*R#5Xhh34gX0H`sIv=Lcw?s!@L0{kiZJf zkVMybM+E6G4n8`gKE`HDP{F>TStKG6!yF6z5oO6ORHNzU+2~}n{}(q)CGw`KlsPe6 zFYCr|=-^&bKoN{F46^{$pdD^;hqt69u)9OlBj{txJfeW2mbB2rF>2X&@)Yf8hqf{J znD<5Zz691|Eo$R7>8RrYeMZwwavEflybH2P&Vt+~&_otlwkV9Wsg{M9ES0qE^Rg5+ zG7WIB11)P+aCuR>SeCjd=GXSf)$FtKN{RnG zrTp>(=_6?8?~C)d^ULXnPnVO)#rS;AD=p{aYPG7$`LzMlp;5iIhechhb?)~+a3|`j zdpLYUJj9O(!}>ChustKm+%~bzXa4_-2+5gK-l?cK>iT%G-KKo0Uwi#rM5jG zm270d91bqv3|k6ePb8?vuIhj*S!kC$1k<>85ZZ(WkHN?iOU>F?24t>m48&w9!iJbChangeFullName) + return true; if (pParent->unFlags & (1 << 0)) { pParent->sT += sPrefixForm; pParent->sFullName += sPrefixForm; + pParent->bChangeFullName = true; // pParent->ClearActions(); return true; } @@ -2802,6 +2805,7 @@ bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm) if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm)) { pParent->sFullName += sPrefixForm; + pParent->bChangeFullName = true; // pParent->ClearActions(); return true; } diff --git a/PdfFile/SrcReader/PdfAnnot.h b/PdfFile/SrcReader/PdfAnnot.h index a3b473757a..280aa02e4f 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -619,6 +619,7 @@ private: unFlags = 0; unRefNum = 0; unRefNumParent = 0; + bChangeFullName = false; } ~CAnnotParent() { @@ -628,6 +629,7 @@ private: void ToWASM(NSWasm::CData& oRes); + bool bChangeFullName; unsigned int unFlags; unsigned int unRefNum; // Номер ссылки на объект unsigned int unMaxLen; // Ограничение на максимальную длину text field From 2ec63f2cb7d3af4c543a9161aee4eaa0cd56002d Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 4 Jul 2025 12:26:42 +0300 Subject: [PATCH 05/19] Change ChangeFullNameAnnot --- PdfFile/SrcReader/PdfAnnot.cpp | 39 ++++++++++++++++++++-------------- PdfFile/SrcReader/PdfAnnot.h | 3 ++- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index 92f1b6e9b6..d42f128372 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -1360,6 +1360,7 @@ CAnnotWidget::CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefI oObj.fetch(xref, &oField); oObj.free(); + m_bChangeFullName = false; m_dFontSize = 0.0; m_unFontStyle = 0; @@ -1603,11 +1604,11 @@ void CAnnotWidget::SetButtonFont(PDFDoc* pdfDoc, AcroFormField* pField, NSFonts: } bool CAnnotWidget::ChangeFullName(const std::string& sPrefixForm) { + m_bChangeFullName = true; if (m_unFlags & (1 << 18)) { m_sT += sPrefixForm; m_sFullName += sPrefixForm; - // ClearActions(); return true; } return false; @@ -2767,7 +2768,7 @@ bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm) return false; CAnnotWidget* pWidget = m_arrAnnots[nAnnot]; - if (pWidget->ChangeFullName(sPrefixForm)) + if (pWidget->m_bChangeFullName) return true; unsigned int unRefNumParent = pWidget->GetRefNumParent(); if (unRefNumParent) @@ -2775,12 +2776,16 @@ bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm) std::vector::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; }); if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm)) { - pWidget->AddFullName(sPrefixForm); - // pWidget->ClearActions(); + const std::string& sFullNameChild = pWidget->GetFullName(); + if (sFullNameChild.empty()) + pWidget->SetFullName((*it)->sFullName); + else + pWidget->SetFullName((*it)->sFullName + "." + sFullNameChild); + pWidget->m_bChangeFullName = true; return true; } } - return false; + return pWidget->ChangeFullName(sPrefixForm); } bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm) { @@ -2790,26 +2795,28 @@ bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm) CAnnotParent* pParent = m_arrParents[nParent]; if (pParent->bChangeFullName) return true; - if (pParent->unFlags & (1 << 0)) - { - pParent->sT += sPrefixForm; - pParent->sFullName += sPrefixForm; - pParent->bChangeFullName = true; - // pParent->ClearActions(); - return true; - } - else if (pParent->unFlags & (1 << 4)) + + if (pParent->unFlags & (1 << 4)) { unsigned int unRefNumParent = pParent->unRefNumParent; std::vector::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; }); if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm)) { - pParent->sFullName += sPrefixForm; + if (pParent->sT.empty()) + pParent->sFullName = (*it)->sFullName; + else + pParent->sFullName = (*it)->sFullName + "." + sPrefixForm; pParent->bChangeFullName = true; - // pParent->ClearActions(); return true; } } + else if (pParent->unFlags & (1 << 0)) + { + pParent->sT += sPrefixForm; + pParent->sFullName += sPrefixForm; + pParent->bChangeFullName = true; + return true; + } return false; } void CAnnots::CAnnotParent::ClearActions() diff --git a/PdfFile/SrcReader/PdfAnnot.h b/PdfFile/SrcReader/PdfAnnot.h index 280aa02e4f..1149762025 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -222,12 +222,13 @@ public: unsigned int GetRefNumParent() { return m_unRefNumParent; } const std::string& GetFullName() { return m_sFullName; } void SetFullName(const std::string& sFullName) { m_sFullName = sFullName; } - void AddFullName(const std::string& sPrefixForm) { m_sFullName += sPrefixForm; } bool ChangeFullName(const std::string& sPrefixForm); void ClearActions(); virtual std::string GetType() = 0; virtual void ToWASM(NSWasm::CData& oRes) override; + bool m_bChangeFullName; + protected: CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID); From 156578ca8217a443997b5c646900ca1088a7469e Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 4 Jul 2025 14:16:48 +0300 Subject: [PATCH 06/19] Fix base64 image --- PdfFile/PdfReader.cpp | 23 ----------------------- PdfFile/PdfWriter.cpp | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 8a24f2aec2..aec1faa148 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1205,29 +1205,6 @@ BYTE* CPdfReader::GetWidgets() std::string sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm; pAnnots->ChangeFullNameAnnot(i, sPrefix); - - /* - const std::string& sFullName = arrAnnots[i]->GetFullName(); - std::map::iterator it = mForms.find(sFullName); - if (it == mForms.end()) - mForms[sFullName] = arrAnnots[i]->GetType(); - else if (mForms[sFullName] != arrAnnots[i]->GetType()) - { - if (iPDF == 0) - { - // error - // throw "Same full names for forms of different types within the same file"; - } - else - { - int nPrefix = 0; - std::string sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(nPrefix); - pAnnots->ChangeFullNameAnnot(i, sPrefix); - while (!pAnnots->ChangeFullNameAnnot(i, sPrefix)) - sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(++nPrefix); - } - } - */ } pAnnots->ToWASM(oRes); diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 007d07549d..fe19aefed8 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -101,6 +101,26 @@ static const long c_BrushTypeRadialGradient = 8002; Aggplus::CImage* ConvertMetafile(NSFonts::IApplicationFonts* pAppFonts, const std::wstring& wsPath, const std::wstring& wsTempDirectory, double dWidth = -1, double dHeight = -1) { + if (wsPath.find(L"base64,") == 0) + { + std::wstring::size_type posZ = wsPath.find(L','); + int nBase64Size = (int)(wsPath.length() - posZ - 1); + const wchar_t* pBase64Data = wsPath.c_str() + posZ + 1; + + char* pBase64Buffer = new char[nBase64Size]; + for (int i = 0; i < nBase64Size; ++i) + pBase64Buffer[i] = (char)pBase64Data[i]; + + int nBufferLen = NSBase64::Base64DecodeGetRequiredLength(nBase64Size); + BYTE* pImageBuffer = new BYTE[nBufferLen + 64]; + + if (NSBase64::Base64Decode(pBase64Buffer, nBase64Size, pImageBuffer, &nBufferLen)) + { + CBgraFrame oFrame; + Aggplus::CImage* pImage = new Aggplus::CImage(); + } + } + CImageFileFormatChecker oImageFormat(wsPath); if (_CXIMAGE_FORMAT_WMF == oImageFormat.eFileType || _CXIMAGE_FORMAT_EMF == oImageFormat.eFileType || From e17b99554da3f0ba6008ad6d76e557ebaf22729d Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 4 Jul 2025 19:40:08 +0300 Subject: [PATCH 07/19] Fix Split mode --- .../graphics/commands/AnnotField.cpp | 5 +++- PdfFile/PdfWriter.cpp | 25 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index e9e1bf3446..6f5727b1b8 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -1153,7 +1153,10 @@ bool CWidgetsInfo::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafil for (int i = 0; i < n; ++i) { std::string sImagePath = pReader->ReadStringA(); - m_arrButtonImg.push_back(pCorrector->GetImagePath(UTF8_TO_U(sImagePath))); + std::wstring sImage = UTF8_TO_U(sImagePath); + if (sImagePath.find("data:") != 0 && !sImagePath.empty()) + sImage = pCorrector->GetImagePath(sImage); + m_arrButtonImg.push_back(sImage); } return true; diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index fe19aefed8..88e36a3e33 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -101,7 +101,7 @@ static const long c_BrushTypeRadialGradient = 8002; Aggplus::CImage* ConvertMetafile(NSFonts::IApplicationFonts* pAppFonts, const std::wstring& wsPath, const std::wstring& wsTempDirectory, double dWidth = -1, double dHeight = -1) { - if (wsPath.find(L"base64,") == 0) + if (wsPath.find(L"data:") == 0) { std::wstring::size_type posZ = wsPath.find(L','); int nBase64Size = (int)(wsPath.length() - posZ - 1); @@ -114,11 +114,13 @@ Aggplus::CImage* ConvertMetafile(NSFonts::IApplicationFonts* pAppFonts, const st int nBufferLen = NSBase64::Base64DecodeGetRequiredLength(nBase64Size); BYTE* pImageBuffer = new BYTE[nBufferLen + 64]; + Aggplus::CImage* pImage = new Aggplus::CImage(); if (NSBase64::Base64Decode(pBase64Buffer, nBase64Size, pImageBuffer, &nBufferLen)) - { - CBgraFrame oFrame; - Aggplus::CImage* pImage = new Aggplus::CImage(); - } + pImage->Decode(pImageBuffer, nBufferLen); + + RELEASEARRAYOBJECTS(pImageBuffer); + RELEASEARRAYOBJECTS(pBase64Buffer); + return pImage; } CImageFileFormatChecker oImageFormat(wsPath); @@ -2922,9 +2924,6 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi std::vector arrForm; for (int i = 0; i < arrBI.size(); ++i) { - if (m_bSplit) - break; - std::wstring wsPath = arrBI[i]; if (wsPath.empty()) { @@ -2934,7 +2933,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi std::wstring sTempImagePath = GetDownloadFile(wsPath, wsTempDirectory); std::wstring wsImagePath = sTempImagePath.empty() ? wsPath : sTempImagePath; - Aggplus::CImage* pCImage = ConvertMetafile(pAppFonts, wsImagePath, GetTempFile(wsTempDirectory)); + Aggplus::CImage* pCImage = ConvertMetafile(pAppFonts, wsImagePath, m_bSplit ? L"" : GetTempFile(wsTempDirectory)); PdfWriter::CImageDict* pImage = LoadImage(pCImage, 255); RELEASEOBJECT(pCImage); @@ -2944,9 +2943,6 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi std::map mAnnots = m_pDocument->GetAnnots(); for (auto it = mAnnots.begin(); it != mAnnots.end(); it++) { - if (m_bSplit) - break; - PdfWriter::CAnnotation* pAnnot = it->second; if (pAnnot->GetAnnotationType() != PdfWriter::AnnotWidget) continue; @@ -3231,6 +3227,8 @@ bool CPdfWriter::DrawText(unsigned char* pCodes, const unsigned int& unLen, cons } bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned int& unLen, const double& dX, const double& dY, const std::wstring& wsUnicodeText) { + if (m_bSplit) + return false; // TODO pdf позволяет создание своего шрифта, но не следует это использовать для воссоздания шрифта запрещенного для редактирования или встраивания Aggplus::CGraphicsPathSimpleConverter simplifier; simplifier.SetRenderer(m_pRenderer); @@ -3404,6 +3402,9 @@ bool CPdfWriter::GetFontPath(const std::wstring &wsFontName, const bool &bBold, if (!bFind) { + if (m_bSplit) + return false; + NSFonts::CFontSelectFormat oFontSelect; oFontSelect.wsName = new std::wstring(wsFontName); oFontSelect.bItalic = new INT(bItalic ? 1 : 0); From 4f957137908849f9b132e3783c10fb2be232b6a3 Mon Sep 17 00:00:00 2001 From: Green Date: Thu, 10 Jul 2025 16:15:10 +0300 Subject: [PATCH 08/19] Fix bug #75723 --- DesktopEditor/raster/Metafile/svg/CSvgFile.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp b/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp index f6df395d0f..49aa94753a 100644 --- a/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp +++ b/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp @@ -79,9 +79,9 @@ bool CSvgFile::GetBounds(double &dX, double &dY, double &dWidth, double &dHeight else dHeight = m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel); - if (0. == dWidth) + if (DBL_EPSILON > dWidth) dWidth = SVG_FILE_WIDTH; - if (0. == dHeight) + if (DBL_EPSILON > dHeight) dHeight = SVG_FILE_HEIGHT; return true; From c67d87b1f0d92c5d2f364d5bec88d4aa33920a81 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Mon, 14 Jul 2025 12:05:54 +0300 Subject: [PATCH 09/19] Fix split button AP --- PdfFile/PdfWriter.cpp | 6 +++--- PdfFile/SrcWriter/Annotation.cpp | 18 +++++++++++++++++- PdfFile/SrcWriter/Annotation.h | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 88e36a3e33..1af238fd11 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -2979,7 +2979,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi } } - if (!pPBWidget->Get("AP")) + if (!pPBWidget->Get("AP") && !m_bSplit) DrawButtonWidget(pAppFonts, pPBWidget, 0, NULL); } @@ -4378,7 +4378,7 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit if (nTP != 1 && !pForm) nTP = 0; - if (nTP != 1) + if (nTP != 1 && !m_bSplit) { PdfWriter::CFontCidTrueType* pFont = pButtonWidget->GetFont(); if (!pFont) @@ -4450,7 +4450,7 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit } } - pButtonWidget->SetAP(pForm, nAP, pCodes, unLen, dShiftX, dShiftY, dLineW, dLineH, ppFonts); + pButtonWidget->SetAP(pForm, nAP, pCodes, unLen, dShiftX, dShiftY, dLineW, dLineH, ppFonts, m_bSplit); RELEASEARRAYOBJECTS(pUnicodes); RELEASEARRAYOBJECTS(pCodes); diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index 1e05de8751..b2e22ce9d5 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -1717,7 +1717,7 @@ namespace PdfWriter m_pMK->Add("AC", new CStringObject(sValue.c_str(), true)); m_wsAC = wsAC; } - void CPushButtonWidget::SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts) + void CPushButtonWidget::SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts, bool bNoAP) { if (!pForm && !pCodes) { @@ -1769,6 +1769,22 @@ namespace PdfWriter } } + if (bNoAP) + { + if (pForm) + { + CheckMK(); + std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX"); + m_pMK->Add(sAP, pForm); + } + else if (m_pMK) + { + std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX"); + m_pMK->Remove(sAP); + } + return; + } + CAnnotAppearanceObject* pAppearance = NULL; m_pResources = new CResourcesDict(NULL, true, false); if (nAP == 0) diff --git a/PdfFile/SrcWriter/Annotation.h b/PdfFile/SrcWriter/Annotation.h index d9c00afc15..6fa8f0f8cb 100644 --- a/PdfFile/SrcWriter/Annotation.h +++ b/PdfFile/SrcWriter/Annotation.h @@ -521,7 +521,7 @@ namespace PdfWriter void SetRC(const std::wstring& wsRC); void SetAC(const std::wstring& wsAC); - void SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts); + void SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts, bool bNoAP = false); const std::wstring& GetCA() { return m_wsCA; } const std::wstring& GetRC() { return m_wsRC; } const std::wstring& GetAC() { return m_wsAC; } From 13e30bf918650da8ecdf7e118f3f662a7c006631 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Mon, 14 Jul 2025 12:54:33 +0300 Subject: [PATCH 10/19] Fix bug 75871 --- PdfFile/PdfWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index d93251a37d..2c1656b668 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -2671,7 +2671,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi int nFlags = pParent->nFlags; // Adobe не может смешивать юникод и utf имена полей if (nFlags & (1 << 0)) - pParentObj->Add("T", new PdfWriter::CStringObject((U_TO_UTF8(pParent->sName)).c_str())); + pParentObj->Add("T", new PdfWriter::CStringObject((U_TO_UTF8(pParent->sName)).c_str(), true)); std::string sFT = m_pDocument->SetParentKids(pParent->nID); PdfWriter::CArrayObject* pKids = dynamic_cast(pParentObj->Get("Kids")); From d123b0f6108091cf629d6be912e0e153aaa1e3cd Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Mon, 14 Jul 2025 14:29:50 +0300 Subject: [PATCH 11/19] fix bug #75882 --- OdfFile/Reader/Converter/xlsxconversioncontext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/OdfFile/Reader/Converter/xlsxconversioncontext.cpp b/OdfFile/Reader/Converter/xlsxconversioncontext.cpp index 56d45d6488..5153d35096 100644 --- a/OdfFile/Reader/Converter/xlsxconversioncontext.cpp +++ b/OdfFile/Reader/Converter/xlsxconversioncontext.cpp @@ -466,6 +466,7 @@ void xlsx_conversion_context::serialize_bookViews(std::wostream & strm) if (false == sheets_[i]->external_ref().empty() && sheets_[i]->name() == *sActiveTable) { CP_XML_ATTR(L"activeTab", i); + break; } } } From 48e2defbcd021a541831e778f0255ba67db854e0 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Mon, 14 Jul 2025 15:55:17 +0300 Subject: [PATCH 12/19] Fix bug 75897 --- PdfFile/lib/xpdf/Gfx.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/PdfFile/lib/xpdf/Gfx.cc b/PdfFile/lib/xpdf/Gfx.cc index 5baf41c4f2..e8264fb6d4 100644 --- a/PdfFile/lib/xpdf/Gfx.cc +++ b/PdfFile/lib/xpdf/Gfx.cc @@ -4347,6 +4347,21 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskColorMap = NULL; // make gcc happy dict->lookup("Mask", &maskObj); dict->lookup("SMask", &smaskObj); + + if (maskObj.isString()) + { + GString* maskStr = maskObj.getString(); + Object oDict, oMaskObj; + oDict.initNull(); + MemStream* stream = new MemStream(maskStr->getCString(), 0, maskStr->getLength(), &oDict); + Parser* parser = new Parser(NULL, new Lexer(NULL, stream), gTrue); + parser->getObj(&oMaskObj); + maskObj.free(); + oMaskObj.copy(&maskObj); + oMaskObj.free(); + delete parser; + } + if (smaskObj.isStream()) { // soft mask if (inlineImg) { From b488623e8174237d5e32c4156a67a987a3461b1e Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Tue, 15 Jul 2025 12:11:33 +0300 Subject: [PATCH 13/19] Fix bug 75958 --- PdfFile/SrcWriter/FontOTWriter.cpp | 3 ++- PdfFile/SrcWriter/FontTT.cpp | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/PdfFile/SrcWriter/FontOTWriter.cpp b/PdfFile/SrcWriter/FontOTWriter.cpp index 2cd23ac93e..c99e5d484e 100644 --- a/PdfFile/SrcWriter/FontOTWriter.cpp +++ b/PdfFile/SrcWriter/FontOTWriter.cpp @@ -4394,7 +4394,8 @@ namespace PdfWriter std::vector subsetGlyphIDs; for (unsigned long i = 0; i < unCodesCount; ++i) subsetGlyphIDs.push_back(pCodeToGID[i]); - // Убедиться, что есть 0 глиф + if (subsetGlyphIDs.empty()) + subsetGlyphIDs.push_back(0); // Добавить зависимые глифы // Они есть в m_vCodeToGid из pCodeToGID. В pUseGlyfs они тоже есть из m_mGlyphs, но только в m_mGlyphs, они имеют false diff --git a/PdfFile/SrcWriter/FontTT.cpp b/PdfFile/SrcWriter/FontTT.cpp index 21419e9543..3dee4ff587 100644 --- a/PdfFile/SrcWriter/FontTT.cpp +++ b/PdfFile/SrcWriter/FontTT.cpp @@ -108,7 +108,10 @@ namespace PdfWriter if (m_pFontFile && m_pFontFileDict) { CStream* pStream = m_pFontFileDict->GetStream(); - m_pFontFile->WriteTTF(pStream); + if (m_pFontFile->GetOpenTypeCFF()) + m_pFontFile->WriteOTF(pStream); + else + m_pFontFile->WriteTTF(pStream); m_pFontFileDict->Add("Length1", pStream->Size()); m_pFontFileDict->SetFilter(STREAM_FILTER_FLATE_DECODE); } From cc6132cd7746bd4965278d5986e888be2eff4a40 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Wed, 16 Jul 2025 19:08:01 +0300 Subject: [PATCH 14/19] For bug 70337 Fix shape rotation and negative position for pdf editor --- DocxRenderer/src/logic/elements/Shape.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/DocxRenderer/src/logic/elements/Shape.cpp b/DocxRenderer/src/logic/elements/Shape.cpp index 52278ad575..1a3c6fdfbf 100644 --- a/DocxRenderer/src/logic/elements/Shape.cpp +++ b/DocxRenderer/src/logic/elements/Shape.cpp @@ -1100,16 +1100,15 @@ namespace NSDocxRenderer // WriteRecord WriteXfrm oWriter.StartRecord(0); oWriter.WriteBYTE(kBin_g_nodeAttributeStart); - oWriter.WriteBYTE(0); oWriter.AddInt(static_cast(left * c_dMMToEMU)); - oWriter.WriteBYTE(1); oWriter.AddInt(static_cast(top * c_dMMToEMU)); - oWriter.WriteBYTE(2); oWriter.AddInt(static_cast(width * c_dMMToEMU)); - oWriter.WriteBYTE(3); oWriter.AddInt(static_cast(height * c_dMMToEMU)); + oWriter.WriteBYTE(0); oWriter.AddSInt(static_cast(left * c_dMMToEMU)); + oWriter.WriteBYTE(1); oWriter.AddSInt(static_cast(top * c_dMMToEMU)); + oWriter.WriteBYTE(2); oWriter.AddSInt(static_cast(width * c_dMMToEMU)); + oWriter.WriteBYTE(3); oWriter.AddSInt(static_cast(height * c_dMMToEMU)); if (fabs(m_dRotation) > c_dMIN_ROTATION) { - double degree = m_dRotation; - if (m_dRotation < 0) degree = 360.0 - m_dRotation; - oWriter.WriteBYTE(10); oWriter.AddInt(degree * c_dDegreeToAngle); + int degree = static_cast(m_dRotation * c_dDegreeToAngle); + oWriter.WriteBYTE(10); oWriter.AddSInt(degree); } oWriter.WriteBYTE(kBin_g_nodeAttributeEnd); oWriter.EndRecord(); From df4e1445f602bdaa1fa4cff2aee5e2a5e1953f39 Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Thu, 17 Jul 2025 10:36:02 +0300 Subject: [PATCH 15/19] fix bug #75800 --- MsBinaryFile/DocFile/VMLShapeMapping.cpp | 3 +- .../ASCOfficeDrawingConverter.cpp | 99 ++++++++++++++++++- .../ASCOfficeDrawingConverter.h | 1 + 3 files changed, 97 insertions(+), 6 deletions(-) diff --git a/MsBinaryFile/DocFile/VMLShapeMapping.cpp b/MsBinaryFile/DocFile/VMLShapeMapping.cpp index 55e7d3aff5..9f79914b0a 100644 --- a/MsBinaryFile/DocFile/VMLShapeMapping.cpp +++ b/MsBinaryFile/DocFile/VMLShapeMapping.cpp @@ -1052,7 +1052,8 @@ namespace DocFileFormat { if (nAdjValues) { - m_pXmlWriter->WriteAttribute(L"arcsize", m_nAdjValues[0]); + double dArcsize = m_nAdjValues[0] / 21600.; + m_pXmlWriter->WriteAttribute(L"arcsize", dArcsize); } } else if (DocFileFormat::msosptPictureFrame == nCode) diff --git a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp index 5bf8ce0801..896bf315aa 100644 --- a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp +++ b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp @@ -2350,7 +2350,10 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX } else { - pPPTShape->SetAdjustment(0, value.GetValue() / 10.); + if (value.GetValue() < 1) + pPPTShape->SetAdjustment(0, value.GetValue() * 10000); + else + pPPTShape->SetAdjustment(0, value.GetValue() / 10.); } } pPPTShape->ReCalculate(); @@ -2560,7 +2563,10 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX if (pPPTShape != NULL) { if (!bSetShape) + { oShapeElem.m_pShape->setBaseShape(CBaseShapePtr(pPPTShape)); + bSetShape = true; + } if (bIsNeedCoordSizes) { LoadCoordSize(oNodeShape, oShapeElem.m_pShape); @@ -3022,13 +3028,13 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX } CheckBrushShape(elem, oNodeShape, pPPTShape); - CheckBorderShape(elem, oNodeShape, pPPTShape); + CheckEffectShape(elem, oNodeShape, pPPTShape); ////test - NSBinPptxRW::CXmlWriter oXml; - elem->toXmlWriter(&oXml); - std::wstring test = oXml.GetXmlString(); + //NSBinPptxRW::CXmlWriter oXml; + //elem->toXmlWriter(&oXml); + //std::wstring test = oXml.GetXmlString(); } @@ -4845,6 +4851,89 @@ void CDrawingConverter::SendMainProps(const std::wstring& strMainProps, std::wst **pMainProps = strMainProps; } } +void CDrawingConverter::CheckEffectShape(PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape) +{ + if (!oElem) return; + + PPTX::Logic::Shape* pShape = dynamic_cast (oElem->GetElem().operator ->()); + PPTX::Logic::Pic* pPicture = dynamic_cast (oElem->GetElem().operator ->()); + + PPTX::Logic::SpPr* pSpPr = NULL; + + if (pShape) pSpPr = &pShape->spPr; + if (pPicture) pSpPr = &pPicture->spPr; + + if (!pSpPr) return; + + XmlUtils::CXmlNode oNodeShadow = oNode.ReadNode(L"v:shadow"); + SimpleTypes::CTrueFalse bShadowEnabled = SimpleTypes::booleanTrue; + + if (oNodeShadow.IsValid()) + { + XmlMacroReadAttributeBase(oNodeShadow, L"on", bShadowEnabled); + } + if (bShadowEnabled.GetBool()) + { + nullable oColor; + nullable oColor2; + nullable_string oId; + nullable oMatrix; + SimpleTypes::CTrueFalse oObscured; + SimpleTypes::Vml::CVml_Vector2D_Units_Or_Percentage oOffset; + SimpleTypes::Vml::CVml_Vector2D_Units_Or_Percentage oOffset2; + nullable oOpacity; + nullable oOrigin; + SimpleTypes::CShadowType oType; + + XmlMacroReadAttributeBase(oNodeShadow, L"id", oId); + XmlMacroReadAttributeBase(oNodeShadow, L"type", oType); + XmlMacroReadAttributeBase(oNodeShadow, L"color", oColor); + XmlMacroReadAttributeBase(oNodeShadow, L"opacity", oOpacity); + XmlMacroReadAttributeBase(oNodeShadow, L"offset", oOffset); + XmlMacroReadAttributeBase(oNodeShadow, L"origin", oOrigin); + XmlMacroReadAttributeBase(oNodeShadow, L"obscured", oObscured); + XmlMacroReadAttributeBase(oNodeShadow, L"color2", oColor2); + XmlMacroReadAttributeBase(oNodeShadow, L"offset2", oOffset2); + XmlMacroReadAttributeBase(oNodeShadow, L"matrix", oMatrix); + + if (false == pSpPr->EffectList.is_init()) + pSpPr->EffectList.List = new PPTX::Logic::EffectLst(); + + PPTX::Logic::EffectLst* pEffectLst = dynamic_cast(pSpPr->EffectList.List.GetPointer()); + + pEffectLst->outerShdw.Init(); + + pEffectLst->outerShdw->Color.Color = new PPTX::Logic::SrgbClr(); + + if (oColor.IsInit()) + pEffectLst->outerShdw->Color.Color->SetRGB(oColor->Get_R(), oColor->Get_G(), oColor->Get_B()); + else + pEffectLst->outerShdw->Color.Color->SetRGB(0x80, 0x80, 0x80); + + if (oOpacity.is_init()) + { + BYTE lAlpha = oOpacity->GetValue() * 255; + + PPTX::Logic::ColorModifier oMod; + oMod.name = L"alpha"; + int nA = (int)(lAlpha * 100000.0 / 255.0); + oMod.val = nA; + pEffectLst->outerShdw->Color.Color->Modifiers.push_back(oMod); + } + double offsetX = oOffset.IsXinPoints() ? oOffset.GetX() : 0; + double offsetY = oOffset.IsYinPoints() ? oOffset.GetY() : 0; + + double dist = sqrt(offsetX * offsetX + offsetY * offsetY); + double dir = (offsetX != 0) ? atan(offsetY / offsetX) * 180. / 3.1415926 : 0; + if (offsetX < 0) dir += 180; + if (dir < 0) dir += 360; + + pEffectLst->outerShdw->dist = dist * (635 * 20); + pEffectLst->outerShdw->dir = (int)(dir * 60000); + pEffectLst->outerShdw->rotWithShape = false; + } + +} void CDrawingConverter::CheckBorderShape(PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape) { if (!oElem) return; diff --git a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h index b7e8b9f468..3fc3dd46f7 100644 --- a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h +++ b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h @@ -298,6 +298,7 @@ namespace NSBinPptxRW void CheckBrushShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); void CheckPenShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); void CheckBorderShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); + void CheckEffectShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); void ConvertColor (PPTX::Logic::UniColor& uniColor, nullable_string& sColor, nullable_string& sOpacity); void LoadCoordSize (XmlUtils::CXmlNode& oNode, ::CShapePtr pShape); From e1b3474a06a894b31e4efb04091ba81c633165a6 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Thu, 17 Jul 2025 17:57:16 +0300 Subject: [PATCH 16/19] Create Redact --- .../graphics/pro/js/wasm/js/drawingfile.js | 5 +- .../pro/js/wasm/src/drawingfile_test.cpp | 74 +++++++++ PdfFile/PdfReader.cpp | 7 + PdfFile/SrcReader/PdfAnnot.cpp | 154 +++++++++++++++++- PdfFile/SrcReader/PdfAnnot.h | 26 +++ PdfFile/lib/xpdf/Page.cc | 2 +- 6 files changed, 261 insertions(+), 7 deletions(-) diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index 0e508fc231..c9d71d930d 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -543,9 +543,8 @@ function readAnnot(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, // User ID if (flags & (1 << 7)) rec["OUserID"] = readStringFunc.call(reader); - // User ID - if (flags & (1 << 8)) - rec["AP"]["Copy"] = reader.readInt(); + // if (flags & (1 << 8)) + // reader.readInt(); } function readAnnotAP(reader, AP) { diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index f8b720a8c1..355f13fd6d 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -2036,6 +2036,80 @@ int main(int argc, char* argv[]) i += 4; std::cout << "Y4 " << (double)nPathLength / 10000.0 << ", "; } + else if (sType == "Redact") + { + if (nFlags & (1 << 15)) + { + std::cout << "QuadPoints"; + int nQuadPointsLength = READ_INT(pAnnots + i); + i += 4; + + for (int j = 0; j < nQuadPointsLength; ++j) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << " " << (double)nPathLength / 100.0; + } + std::cout << ", "; + } + if (nFlags & (1 << 16)) + { + int nICLength = READ_INT(pAnnots + i); + i += 4; + std::cout << "IC "; + + for (int j = 0; j < nICLength; ++j) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << (double)nPathLength / 10000.0 << " "; + } + std::cout << ", "; + } + if (nFlags & (1 << 17)) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << "OverlayText " << std::string((char*)(pAnnots + i), nPathLength) << ", "; + i += nPathLength; + } + if (nFlags & (1 << 18)) + std::cout << "Repeat true, "; + else + std::cout << "Repeat false, "; + if (nFlags & (1 << 19)) + { + std::string arrQ[] = {"left-justified", "centered", "right-justified"}; + nPathLength = READ_BYTE(pAnnots + i); + i += 1; + std::cout << "Q " << arrQ[nPathLength] << ", "; + } + if (nFlags & (1 << 20)) + { + int nICLength = READ_INT(pAnnots + i); + i += 4; + std::cout << "DA color "; + + for (int j = 0; j < nICLength; ++j) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << (double)nPathLength / 10000.0 << " "; + } + std::cout << ", size "; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << (double)nPathLength / 100.0 << ", font "; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << std::string((char*)(pAnnots + i), nPathLength) << " actual "; + i += nPathLength; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << std::string((char*)(pAnnots + i), nPathLength) << ", "; + i += nPathLength; + } + } std::cout << std::endl << "]" << std::endl; } diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 876378e611..0cea78bb30 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1985,6 +1985,13 @@ int GetPageAnnots(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, PdfReader { pAnnot = new PdfReader::CAnnotInk(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); } + else if (sType == "Redact") + { + PdfReader::CAnnotRedact* pRedact = new PdfReader::CAnnotRedact(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); + std::map mFont = PdfReader::CAnnotFonts::GetAnnotFont(pdfDoc, pFontManager, pFontList, &oAnnotRef); + pRedact->SetFont(mFont); + pAnnot = pRedact; + } // else if (sType == "FileAttachment") // { // pAnnot = new PdfReader::CAnnotFileAttachment(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index 0aafb5198f..85742e134b 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -860,10 +860,14 @@ std::map CAnnotFonts::GetAnnotFont(PDFDoc* pdfDoc, N std::map mFontFreeText; Object oAP, oN; - if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("N", &oN)->isStream()) + if (!oAnnot.dictLookup("RO", &oN)->isStream()) { - oAP.free(); oN.free(); oAnnot.free(); - return mFontFreeText; + oN.free(); + if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("N", &oN)->isStream()) + { + oAP.free(); oN.free(); oAnnot.free(); + return mFontFreeText; + } } oAP.free(); @@ -2428,6 +2432,118 @@ CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int oAnnot.free(); } +//------------------------------------------------------------------------ +// Redact +//------------------------------------------------------------------------ + +CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID) +{ + Object oAnnot, oObj, oObj2; + XRef* pXref = pdfDoc->getXRef(); + oAnnotRef->fetch(pXref, &oAnnot); + + // 15 - Координаты - QuadPoints + if (oAnnot.dictLookup("QuadPoints", &oObj)->isArray()) + { + m_unFlags |= (1 << 15); + for (int i = 0; i < oObj.arrayGetLength(); ++i) + { + if (oObj.arrayGet(i, &oObj2)->isNum()) + m_arrQuadPoints.push_back(i % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum()); + oObj2.free(); + } + } + oObj.free(); + + // 16 - Цвет заполнения - IC + if (oAnnot.dictLookup("IC", &oObj)->isArray()) + { + m_unFlags |= (1 << 16); + for (int j = 0; j < oObj.arrayGetLength(); ++j) + { + m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0); + oObj2.free(); + } + } + oObj.free(); + + // RO во внешних видах + + // 17 - Текст наложения - OverlayText + m_sOverlayText = DictLookupString(&oAnnot, "OverlayText", 17); + + // 18 - Повторять текст - Repeat + if (oAnnot.dictLookup("Repeat", &oObj)->isBool() && oObj.getBool()) + m_unFlags |= (1 << 18); + + // 19 - Выравнивание текста - Q + m_nQ = 0; + if (oAnnot.dictLookup("Q", &oObj)->isInt()) + { + m_unFlags |= (1 << 19); + m_nQ = oObj.getInt(); + } + oObj.free(); + + // 20 - Шрифт, размер, цвет текста замены - DA + if (oAnnot.dictLookup("DA", &oObj)->isString()) + { + m_unFlags |= (1 << 20); + // parse the default appearance string + GList* daToks = tokenize(oObj.getString()); + for (int i = daToks->getLength() - 1; i > 0; --i) + { + // handle the g operator + if (!((GString *)daToks->get(i))->cmp("G") && m_arrCFromDA.empty()) + { + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString())); + } + // handle the rg operator + else if (i >= 3 && !((GString *)daToks->get(i))->cmp("RG") && m_arrCFromDA.empty()) + { + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString())); + } + // handle the k operator + else if (i >= 4 && !((GString *)daToks->get(i))->cmp("K") && m_arrCFromDA.empty()) + { + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 4))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString())); + } + else if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) + { + m_dFontSize = atof(((GString *)daToks->get(i - 1))->getCString()); + } + } + deleteGList(daToks, GString); + } + oObj.free(); + + oAnnot.free(); +} +void CAnnotRedact::SetFont(const std::map& mFont) +{ + if (mFont.empty()) + return; + std::map::const_iterator it = mFont.begin(); + std::wstring sFont = it->first; + m_sActualFontName = U_TO_UTF8(sFont); + if (mFont.size() > 1) + { + ++it; + sFont = it->first; + m_sFontName = U_TO_UTF8(sFont); + } + else + { + m_sFontName = m_sActualFontName; + m_sActualFontName.clear(); + } +} + //------------------------------------------------------------------------ // Annots //------------------------------------------------------------------------ @@ -4327,4 +4443,36 @@ void CAnnotStamp::ToWASM(NSWasm::CData& oRes) oRes.WriteDouble(m_dX4); oRes.WriteDouble(m_dY4); } +void CAnnotRedact::ToWASM(NSWasm::CData& oRes) +{ + oRes.WriteBYTE(25); // Redact + + CAnnotMarkup::ToWASM(oRes); + + if (m_unFlags & (1 << 15)) + { + oRes.AddInt((unsigned int)m_arrQuadPoints.size()); + for (int i = 0; i < m_arrQuadPoints.size(); ++i) + oRes.AddDouble(m_arrQuadPoints[i]); + } + if (m_unFlags & (1 << 16)) + { + oRes.AddInt((unsigned int)m_arrIC.size()); + for (int i = 0; i < m_arrIC.size(); ++i) + oRes.WriteDouble(m_arrIC[i]); + } + if (m_unFlags & (1 << 17)) + oRes.WriteString(m_sOverlayText); + if (m_unFlags & (1 << 19)) + oRes.WriteBYTE(m_nQ); + if (m_unFlags & (1 << 20)) + { + oRes.AddInt((unsigned int)m_arrCFromDA.size()); + for (int i = 0; i < m_arrCFromDA.size(); ++i) + oRes.WriteDouble(m_arrCFromDA[i]); + oRes.AddDouble(m_dFontSize); + oRes.WriteString(m_sFontName); + oRes.WriteString(m_sActualFontName); + } +} } diff --git a/PdfFile/SrcReader/PdfAnnot.h b/PdfFile/SrcReader/PdfAnnot.h index d1ed82e77f..6deab1e326 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -590,12 +590,38 @@ public: CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID); void ToWASM(NSWasm::CData& oRes) override; + private: std::string m_sName; // Иконка double m_dRotate; double m_dX1, m_dY1, m_dX2, m_dY2, m_dX3, m_dY3, m_dX4, m_dY4; }; +//------------------------------------------------------------------------ +// PdfReader::CAnnotRedact +//------------------------------------------------------------------------ + +class CAnnotRedact final : public CAnnotMarkup +{ +public: + CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID); + + void SetFont(const std::map& mFont); + + void ToWASM(NSWasm::CData& oRes) override; + +private: + BYTE m_nQ; // Выравнивание текста + unsigned int m_unFontStyle; // Стиль шрифта - из DA + double m_dFontSize; // Размер шрифта - из DA + std::string m_sFontName; // Имя шрифта - из DA + std::string m_sActualFontName; // Имя замененного шрифта + std::string m_sOverlayText; // Текст наложения + std::vector m_arrQuadPoints; // Координаты + std::vector m_arrIC; // Цвет заполнения + std::vector m_arrCFromDA; // Цвет текста +}; + //------------------------------------------------------------------------ // PdfReader::CAnnots //------------------------------------------------------------------------ diff --git a/PdfFile/lib/xpdf/Page.cc b/PdfFile/lib/xpdf/Page.cc index 05b03ce739..df078072c2 100644 --- a/PdfFile/lib/xpdf/Page.cc +++ b/PdfFile/lib/xpdf/Page.cc @@ -395,7 +395,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, sType = annotList->getAnnot(i)->getType(); if (globalParams->getDrawAnnotations() || sType->cmp("Link") == 0 || sType->cmp("FileAttachment") == 0 || sType->cmp("Sound") == 0 || sType->cmp("Movie") == 0 || sType->cmp("Screen") == 0 || sType->cmp("PrinterMark") == 0 || - sType->cmp("TrapNet") == 0 || sType->cmp("Watermark") == 0 || sType->cmp("3D") == 0 || sType->cmp("Redact") == 0) + sType->cmp("TrapNet") == 0 || sType->cmp("Watermark") == 0 || sType->cmp("3D") == 0) annotList->getAnnot(i)->draw(gfx, printing); } } From 0c601c1c82bd7acbe8042c255db49beb865f5ce9 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 18 Jul 2025 12:02:20 +0300 Subject: [PATCH 17/19] Redact read font from DA --- .../graphics/pro/js/wasm/js/drawingfile.js | 80 ++++++++++++++----- .../pro/js/wasm/src/drawingfile_test.cpp | 5 +- PdfFile/PdfReader.cpp | 3 +- PdfFile/SrcReader/PdfAnnot.cpp | 68 +++++++++++----- PdfFile/SrcReader/PdfAnnot.h | 3 +- 5 files changed, 116 insertions(+), 43 deletions(-) diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index c9d71d930d..bc1bdd37d5 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -580,7 +580,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF { // Markup let flags = 0; - if ((rec["Type"] < 18 && rec["Type"] != 1 && rec["Type"] != 15) || rec["Type"] == 25) + if ((rec["type"] < 18 && rec["type"] != 1 && rec["type"] != 15) || rec["type"] == 25) { flags = reader.readInt(); if (flags & (1 << 0)) @@ -635,7 +635,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["Subj"] = readStringFunc.call(reader); } // Text - if (rec["Type"] == 0) + if (rec["type"] == 0) { // Background color - C->IC if (rec["C"]) @@ -659,7 +659,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } // Line - else if (rec["Type"] == 3) + else if (rec["type"] == 3) { // L rec["L"] = []; @@ -709,7 +709,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Ink - else if (rec["Type"] == 14) + else if (rec["type"] == 14) { // offsets like getStructure and viewer.navigate let n = reader.readInt(); @@ -723,7 +723,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Highlight, Underline, Squiggly, Strikeout - else if (rec["Type"] > 7 && rec["Type"] < 12) + else if (rec["type"] > 7 && rec["type"] < 12) { // QuadPoints let n = reader.readInt(); @@ -732,7 +732,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["QuadPoints"].push(readDoubleFunc.call(reader)); } // Square, Circle - else if (rec["Type"] == 4 || rec["Type"] == 5) + else if (rec["type"] == 4 || rec["type"] == 5) { // Rect and RD differences if (flags & (1 << 15)) @@ -751,7 +751,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Polygon, PolyLine - else if (rec["Type"] == 6 || rec["Type"] == 7) + else if (rec["type"] == 6 || rec["type"] == 7) { let nVertices = reader.readInt(); rec["Vertices"] = []; @@ -779,8 +779,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["IT"] = reader.readByte(); } // Popup - /* - else if (rec["Type"] == 15) + else if (rec["type"] == 15) { flags = reader.readInt(); rec["Open"] = (flags >> 0) & 1; @@ -788,9 +787,8 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF if (flags & (1 << 1)) rec["PopupParent"] = reader.readInt(); } - */ // FreeText - else if (rec["Type"] == 2) + else if (rec["type"] == 2) { // Background color - C->IC if (!isRead && rec["C"]) @@ -846,7 +844,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Caret - else if (rec["Type"] == 13) + else if (rec["type"] == 13) { // Rect and RD differenses if (flags & (1 << 15)) @@ -861,7 +859,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["Sy"] = reader.readByte(); } // FileAttachment - else if (rec["Type"] == 16) + else if (rec["type"] == 16) { if (flags & (1 << 15)) rec["Icon"] = readStringFunc.call(reader); @@ -960,7 +958,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["Desc"] = readStringFunc.call(reader); } // Stamp - else if (rec["Type"] == 12) + else if (rec["type"] == 12) { rec["Icon"] = readStringFunc.call(reader); rec["Rotate"] = readDouble2Func.call(reader); @@ -968,6 +966,52 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF for (let i = 0; i < 8; ++i) rec["InRect"].push(readDouble2Func.call(reader)); } + // Redact + else if (rec["type"] == 25) + { + // QuadPoints + if (flags & (1 << 15)) + { + let n = reader.readInt(); + rec["QuadPoints"] = []; + for (let i = 0; i < n; ++i) + rec["QuadPoints"].push(readDoubleFunc.call(reader)); + } + // IC + if (flags & (1 << 16)) + { + let n = reader.readInt(); + rec["IC"] = []; + for (let i = 0; i < n; ++i) + rec["IC"].push(readDouble2Func.call(reader)); + } + // OverlayText + if (flags & (1 << 17)) + rec["OverlayText"] = readStringFunc.call(reader); + // Repeat + rec["Repeat"] = (flags >> 18) & 1; + // Q - alignment + if (flags & (1 << 19)) + { + // 0 - left-justified, 1 - centered, 2 - right-justified + rec["alignment"] = reader.readByte(); + } + // Font from DA + if (flags & (1 << 20)) + { + rec["font"] = {}; + let n = reader.readInt(); + rec["font"]["color"] = []; + for (let i = 0; i < n; ++i) + rec["font"]["color"].push(readDouble2Func.call(reader)); + rec["font"]["size"] = readDoubleFunc.call(reader); + rec["font"]["name"] = readStringFunc.call(reader); + let fontActual = readStringFunc.call(reader); + if (fontActual != "") + rec["font"]["actual"] = fontActual; + rec["font"]["style"] = reader.readInt(); + } + } } function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, isRead = false) { @@ -986,7 +1030,7 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString rec["font"]["color"].push(readDouble2Func.call(reader)); } // 0 - left-justified, 1 - centered, 2 - right-justified - if (!isRead || (rec["Type"] != 29 && rec["Type"] != 28 && rec["Type"] != 27)) + if (!isRead || (rec["type"] != 29 && rec["type"] != 28 && rec["type"] != 27)) rec["alignment"] = reader.readByte(); rec["flag"] = reader.readInt(); // 12.7.3.1 @@ -1470,7 +1514,7 @@ CFile.prototype["getAnnotationsInfo"] = function(pageIndex) // 11 - Strikeout, 12 - Stamp, 13 - Caret, 14 - Ink, 15 - Popup, 16 - FileAttachment, // 17 - Sound, 18 - Movie, 19 - Widget, 20 - Screen, 21 - PrinterMark, // 22 - TrapNet, 23 - Watermark, 24 - 3D, 25 - Redact - rec["Type"] = reader.readByte(); + rec["type"] = reader.readByte(); // Annot readAnnot(reader, rec, reader.readDouble, reader.readDouble2, reader.readString); // Annot type @@ -1545,12 +1589,12 @@ CFile.prototype["readAnnotationsInfoFromBinary"] = function(AnnotInfo) // 11 - Strikeout, 12 - Stamp, 13 - Caret, 14 - Ink, 15 - Popup, 16 - FileAttachment, // 17 - Sound, 18 - Movie, 19 - Widget, 20 - Screen, 21 - PrinterMark, // 22 - TrapNet, 23 - Watermark, 24 - 3D, 25 - Redact - rec["Type"] = reader.readByte(); + rec["type"] = reader.readByte(); // Annot readAnnot(reader, rec, reader.readDouble3, reader.readDouble3, reader.readString2, true); // Annot type readAnnotType(reader, rec, reader.readDouble3, reader.readDouble3, reader.readString2, true); - if (rec["Type"] >= 26 && rec["Type"] <= 33) + if (rec["type"] >= 26 && rec["type"] <= 33) { // Widget type readWidgetType(reader, rec, reader.readDouble3, reader.readDouble3, reader.readString2, true); diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index 355f13fd6d..9d7888b1c2 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -2106,8 +2106,11 @@ int main(int argc, char* argv[]) i += nPathLength; nPathLength = READ_INT(pAnnots + i); i += 4; - std::cout << std::string((char*)(pAnnots + i), nPathLength) << ", "; + std::cout << std::string((char*)(pAnnots + i), nPathLength) << ", style "; i += nPathLength; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << nPathLength << ", "; } } diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 0cea78bb30..deb25df5c1 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1988,8 +1988,7 @@ int GetPageAnnots(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, PdfReader else if (sType == "Redact") { PdfReader::CAnnotRedact* pRedact = new PdfReader::CAnnotRedact(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); - std::map mFont = PdfReader::CAnnotFonts::GetAnnotFont(pdfDoc, pFontManager, pFontList, &oAnnotRef); - pRedact->SetFont(mFont); + pRedact->SetFont(pdfDoc, pFontManager, pFontList, &oAnnotRef); pAnnot = pRedact; } // else if (sType == "FileAttachment") diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index 85742e134b..4158ac1069 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -860,14 +860,10 @@ std::map CAnnotFonts::GetAnnotFont(PDFDoc* pdfDoc, N std::map mFontFreeText; Object oAP, oN; - if (!oAnnot.dictLookup("RO", &oN)->isStream()) + if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("N", &oN)->isStream()) { - oN.free(); - if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("N", &oN)->isStream()) - { - oAP.free(); oN.free(); oAnnot.free(); - return mFontFreeText; - } + oAP.free(); oN.free(); oAnnot.free(); + return mFontFreeText; } oAP.free(); @@ -2516,6 +2512,7 @@ CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, in else if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) { m_dFontSize = atof(((GString *)daToks->get(i - 1))->getCString()); + m_unFontStyle = 0; } } deleteGList(daToks, GString); @@ -2524,24 +2521,54 @@ CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, in oAnnot.free(); } -void CAnnotRedact::SetFont(const std::map& mFont) +void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef) { - if (mFont.empty()) + Object oAnnot, oObj; + XRef* pXref = pdfDoc->getXRef(); + oAnnotRef->fetch(pXref, &oAnnot); + + Object oAP, oN; + if (!oAnnot.dictLookup("RO", &oN)->isStream()) + { + oN.free(); + if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("D", &oN)->isStream()) + { + oAP.free(); oN.free(); oAnnot.free(); + return; + } + } + oAP.free(); + + Object oFonts; + if (!CAnnotFonts::FindFonts(&oN, 0, &oFonts)) + { + oN.free(); oFonts.free(); oAnnot.free(); return; - std::map::const_iterator it = mFont.begin(); - std::wstring sFont = it->first; - m_sActualFontName = U_TO_UTF8(sFont); - if (mFont.size() > 1) - { - ++it; - sFont = it->first; - m_sFontName = U_TO_UTF8(sFont); } - else + oN.free(); + + for (int i = 0, nFonts = oFonts.dictGetLength(); i < nFonts; ++i) { - m_sFontName = m_sActualFontName; - m_sActualFontName.clear(); + Object oFontRef; + if (!oFonts.dictGetValNF(i, &oFontRef)->isRef()) + { + oFontRef.free(); + continue; + } + + std::string sFontName, sActualFontName; + bool bBold = false, bItalic = false; + std::wstring sFontPath = CAnnotFonts::GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sFontName, m_sActualFontName, bBold, bItalic); + oFontRef.free(); + + m_unFontStyle = 0; + if (bBold) + m_unFontStyle |= (1 << 0); + if (bItalic) + m_unFontStyle |= (1 << 1); } + + oFonts.free(); oAnnot.free(); } //------------------------------------------------------------------------ @@ -4473,6 +4500,7 @@ void CAnnotRedact::ToWASM(NSWasm::CData& oRes) oRes.AddDouble(m_dFontSize); oRes.WriteString(m_sFontName); oRes.WriteString(m_sActualFontName); + oRes.AddInt(m_unFontStyle); } } } diff --git a/PdfFile/SrcReader/PdfAnnot.h b/PdfFile/SrcReader/PdfAnnot.h index 6deab1e326..5d6bfb2938 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -606,7 +606,7 @@ class CAnnotRedact final : public CAnnotMarkup public: CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID); - void SetFont(const std::map& mFont); + void SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef); void ToWASM(NSWasm::CData& oRes) override; @@ -689,7 +689,6 @@ public: static bool GetFontFromAP(PDFDoc* pdfDoc, AcroFormField* pField, Object* oFontRef, std::string& sFontKey); static std::map GetAnnotFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef); static std::map GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector& arrRC); -private: static bool FindFonts(Object* oStream, int nDepth, Object* oResFonts); }; From 5ec24525b84cf5e8e644a8190122ca3efb474d84 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 18 Jul 2025 13:25:11 +0300 Subject: [PATCH 18/19] Not need AP --- .../graphics/pro/js/wasm/js/drawingfile.js | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index bc1bdd37d5..a22689bb10 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -450,10 +450,13 @@ function readAction(reader, rec, readDoubleFunc, readStringFunc) } function readAnnot(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, isRead = false) { - rec["AP"] = {}; + if (!isRead) + rec["AP"] = {}; // Annot // number for relations with AP - rec["AP"]["i"] = reader.readInt(); + let APi = reader.readInt(); + if (!isRead) + rec["AP"]["i"] = APi; rec["annotflag"] = reader.readInt(); // 12.5.3 let bHidden = (rec["annotflag"] >> 1) & 1; // Hidden @@ -536,7 +539,10 @@ function readAnnot(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, if (flags & (1 << 6)) { if (isRead) - rec["AP"]["render"] = reader.readData(); // TODO use Render - Uint8Array + { + let APrender = reader.readData(); // TODO use Render - Uint8Array + // rec["AP"]["render"] = APrender; + } else rec["AP"]["have"] = (flags >> 6) & 1; } @@ -1174,9 +1180,15 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString if (isRead) { if (flags & (1 << 12)) - rec["AP"]["V"] = readStringFunc.call(reader); + { + let APV = readStringFunc.call(reader); + // rec["AP"]["V"] = APV; + } if (flags & (1 << 13)) - rec["AP"]["render"] = reader.readData(); // TODO use Render - Uint8Array + { + let APrender = reader.readData(); // TODO use Render - Uint8Array + // rec["AP"]["render"] = APrender; + } } // 12.7.4.3 if (rec["flag"] >= 0) @@ -1213,7 +1225,10 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString if (isRead) { if (flags & (1 << 12)) - rec["AP"]["V"] = readStringFunc.call(reader); + { + let APV = readStringFunc.call(reader); + // rec["AP"]["V"] = APV; + } } else { @@ -1242,7 +1257,10 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString rec["I"].push(reader.readInt()); } if (flags & (1 << 15)) - rec["AP"]["render"] = reader.readData(); // TODO use Render - Uint8Array + { + let APrender = reader.readData(); // TODO use Render - Uint8Array + // rec["AP"]["render"] = APrender; + } } // 12.7.4.4 if (rec["flag"] >= 0) From f45b3ba0daef393cfbc17475342ea8834e4267be Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 18 Jul 2025 14:24:27 +0300 Subject: [PATCH 19/19] Fix DA in SetFont --- PdfFile/SrcReader/PdfAnnot.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index 4158ac1069..8ad8cfa6bf 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -2481,6 +2481,14 @@ CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, in } oObj.free(); + oAnnot.free(); +} +void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef) +{ + Object oAnnot, oObj; + XRef* pXref = pdfDoc->getXRef(); + oAnnotRef->fetch(pXref, &oAnnot); + // 20 - Шрифт, размер, цвет текста замены - DA if (oAnnot.dictLookup("DA", &oObj)->isString()) { @@ -2519,14 +2527,6 @@ CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, in } oObj.free(); - oAnnot.free(); -} -void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef) -{ - Object oAnnot, oObj; - XRef* pXref = pdfDoc->getXRef(); - oAnnotRef->fetch(pXref, &oAnnot); - Object oAP, oN; if (!oAnnot.dictLookup("RO", &oN)->isStream()) {