diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index ef320391e1..6602fd6ad4 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -676,7 +676,7 @@ void CAnnotFieldInfo::CWidgetAnnotPr::Read(NSOnlineOfficeBinToPdf::CBufferReader m_arrTC.push_back(pReader->ReadDouble()); m_nQ = 0; - if (nType != 29 && nType != 28) + if (nType != 29 && nType != 28 && nType != 27) m_nQ = pReader->ReadByte(); int nWidgetFlag = pReader->ReadInt(); m_nFlag = nWidgetFlag; @@ -732,38 +732,47 @@ void CAnnotFieldInfo::CWidgetAnnotPr::Read(NSOnlineOfficeBinToPdf::CBufferReader } void CAnnotFieldInfo::CWidgetAnnotPr::CButtonWidgetPr::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, BYTE nType, int nFlags) { - if (nFlags & (1 << 9)) - m_wsV = pReader->ReadString(); - int nIFFlags = pReader->ReadInt(); - m_nIFFlag = nIFFlags; if (nType == 27) { + m_nIFFlag = pReader->ReadInt(); + if (nFlags & (1 << 10)) m_wsCA = pReader->ReadString(); if (nFlags & (1 << 11)) m_wsRC = pReader->ReadString(); if (nFlags & (1 << 12)) m_wsAC = pReader->ReadString(); + if (nFlags & (1 << 13)) + m_nTP = pReader->ReadByte(); + + if (m_nIFFlag & (1 << 0)) + { + if (m_nIFFlag & (1 << 1)) + m_nSW = pReader->ReadByte(); + if (m_nIFFlag & (1 << 2)) + m_nS = pReader->ReadByte(); + if (m_nIFFlag & (1 << 3)) + { + m_dA1 = pReader->ReadDouble(); + m_dA2 = pReader->ReadDouble(); + } + } + + if (m_nIFFlag & (1 << 5)) + m_nI = pReader->ReadInt(); + if (m_nIFFlag & (1 << 6)) + m_nRI = pReader->ReadInt(); + if (m_nIFFlag & (1 << 7)) + m_nIX = pReader->ReadInt(); } else - m_nStyle = pReader->ReadByte(); - - if (nFlags & (1 << 13)) - m_nTP = pReader->ReadByte(); - if (nIFFlags & (1 << 0)) { - if (nIFFlags & (1 << 1)) - m_nSW = pReader->ReadByte(); - if (nIFFlags & (1 << 2)) - m_nS = pReader->ReadByte(); - if (nIFFlags & (1 << 3)) - { - m_dA1 = pReader->ReadDouble(); - m_dA2 = pReader->ReadDouble(); - } + if (nFlags & (1 << 9)) + m_wsV = pReader->ReadString(); + m_nStyle = pReader->ReadByte(); + if (nFlags & (1 << 14)) + m_wsAP_N_Yes = pReader->ReadString(); } - if (nFlags & (1 << 14)) - m_wsAP_N_Yes = pReader->ReadString(); } void CAnnotFieldInfo::CWidgetAnnotPr::CTextWidgetPr::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, int nFlags, int nWidgetFlag) { @@ -829,5 +838,9 @@ bool CWidgetsInfo::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafil m_arrParents.push_back(pParent); } + n = pReader->ReadInt(); + for (int i = 0; i < n; ++i) + m_arrButtonImg.push_back(pCorrector->GetImagePath(pReader->ReadString())); + return true; } diff --git a/DesktopEditor/graphics/commands/AnnotField.h b/DesktopEditor/graphics/commands/AnnotField.h index a51b85f572..56d466dcdc 100644 --- a/DesktopEditor/graphics/commands/AnnotField.h +++ b/DesktopEditor/graphics/commands/AnnotField.h @@ -62,6 +62,9 @@ public: BYTE GetSW() const { return m_nSW; } BYTE GetStyle() const { return m_nStyle; } int GetIFFlag() const { return m_nIFFlag; } + int GetI() const { return m_nI; } + int GetRI() const { return m_nRI; } + int GetIX() const { return m_nIX; } void GetA(double& dA1, double& dA2) const { dA1 = m_dA1; dA2 = m_dA2; } const std::wstring& GetV() const { return m_wsV; } const std::wstring& GetCA() const { return m_wsCA; } @@ -77,6 +80,9 @@ public: BYTE m_nSW; BYTE m_nStyle; int m_nIFFlag; + int m_nI; + int m_nRI; + int m_nIX; double m_dA1, m_dA2; std::wstring m_wsV; std::wstring m_wsCA; @@ -495,12 +501,14 @@ public: virtual ~CWidgetsInfo(); const std::vector& GetCO() const { return m_arrCO; } + const std::vector& GetButtonImg() const { return m_arrButtonImg; } const std::vector& GetParents() const { return m_arrParents; } bool Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRenderter* pCorrector); private: std::vector m_arrCO; + std::vector m_arrButtonImg; std::vector m_arrParents; }; diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js index 896584bab4..4865df759b 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js @@ -789,27 +789,20 @@ readAction(reader, rec["AA"][AAType]); } // Widget types - if (rec["type"] == 29 || rec["type"] == 28 || rec["type"] == 27) + if (rec["type"] == 27) { if (flags & (1 << 9)) rec["value"] = reader.readString(); let IFflags = reader.readInt(); - // MK - if (rec["type"] == 27) - { - // Header - СA - if (flags & (1 << 10)) - rec["caption"] = reader.readString(); - // Rollover header - RC - if (flags & (1 << 11)) - rec["rolloverCaption"] = reader.readString(); - // Alternate header - AC - if (flags & (1 << 12)) - rec["alternateCaption"] = reader.readString(); - } - else - // 0 - check, 1 - cross, 2 - diamond, 3 - circle, 4 - star, 5 - square - rec["style"] = reader.readByte(); + // Header - СA + if (flags & (1 << 10)) + rec["caption"] = reader.readString(); + // Rollover header - RC + if (flags & (1 << 11)) + rec["rolloverCaption"] = reader.readString(); + // Alternate header - AC + if (flags & (1 << 12)) + rec["alternateCaption"] = reader.readString(); // Header position - TP if (flags & (1 << 13)) // 0 - textOnly, 1 - iconOnly, 2 - iconTextV, 3 - textIconV, 4 - iconTextH, 5 - textIconH, 6 - overlay @@ -834,6 +827,13 @@ } rec["IF"]["FB"] = (IFflags >> 4) & 1; } + } + else if (rec["type"] == 29 || rec["type"] == 28) + { + if (flags & (1 << 9)) + rec["value"] = reader.readString(); + // 0 - check, 1 - cross, 2 - diamond, 3 - circle, 4 - star, 5 - square + rec["style"] = reader.readByte(); if (flags & (1 << 14)) rec["ExportValue"] = reader.readString(); // 12.7.4.2.1 diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index dfdb594998..b66b81785c 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -491,7 +491,7 @@ void ReadInteractiveForms(BYTE* pWidgets, int& i) // Widget types - if (sType == "checkbox" || sType == "radiobutton" || sType == "button") + if (sType == "button") { if (nFlags & (1 << 9)) { @@ -504,36 +504,26 @@ void ReadInteractiveForms(BYTE* pWidgets, int& i) int nIFFlag = READ_INT(pWidgets + i); i += 4; - if (sType == "button") + if (nFlags & (1 << 10)) { - if (nFlags & (1 << 10)) - { - nPathLength = READ_INT(pWidgets + i); - i += 4; - std::cout << "CA " << std::string((char*)(pWidgets + i), nPathLength) << ", "; - i += nPathLength; - } - if (nFlags & (1 << 11)) - { - nPathLength = READ_INT(pWidgets + i); - i += 4; - std::cout << "RC " << std::string((char*)(pWidgets + i), nPathLength) << ", "; - i += nPathLength; - } - if (nFlags & (1 << 12)) - { - nPathLength = READ_INT(pWidgets + i); - i += 4; - std::cout << "AC " << std::string((char*)(pWidgets + i), nPathLength) << ", "; - i += nPathLength; - } + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "CA " << std::string((char*)(pWidgets + i), nPathLength) << ", "; + i += nPathLength; } - else + if (nFlags & (1 << 11)) { - std::string arrStyle[] = {"check", "cross", "diamond", "circle", "star", "square"}; - nPathLength = READ_BYTE(pWidgets + i); - i += 1; - std::cout << "Style " << arrStyle[nPathLength] << ", "; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "RC " << std::string((char*)(pWidgets + i), nPathLength) << ", "; + i += nPathLength; + } + if (nFlags & (1 << 12)) + { + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "AC " << std::string((char*)(pWidgets + i), nPathLength) << ", "; + i += nPathLength; } if (nFlags & (1 << 13)) { @@ -570,6 +560,22 @@ void ReadInteractiveForms(BYTE* pWidgets, int& i) } std::cout << "FB " << (nIFFlag & (1 << 4)) << ", "; } + } + else if (sType == "checkbox" || sType == "radiobutton") + { + if (nFlags & (1 << 9)) + { + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "Value " << std::string((char*)(pWidgets + i), nPathLength) << ", "; + i += nPathLength; + } + + std::string arrStyle[] = {"check", "cross", "diamond", "circle", "star", "square"}; + nPathLength = READ_BYTE(pWidgets + i); + i += 1; + std::cout << "Style " << arrStyle[nPathLength] << ", "; + if (nFlags & (1 << 14)) { nPathLength = READ_INT(pWidgets + i); diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index 821e7fb8e8..f1837aba5a 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -898,7 +898,37 @@ bool CPdfFile::EditAnnot(int nPageIndex, int nID) if (sName) { if (strcmp("Btn", sName) == 0) - pAnnot = new PdfWriter::CButtonWidget(pXref); + { + bool bPushButton = false; + oFT.free(); + int nFf = 0; + if (oAnnot.dictLookup("Ff", &oFT)->isInt()) + nFf = oFT.getInt(); + if (!nFf) + { + Object oParent, oParent2; + oAnnot.dictLookup("Parent", &oParent); + while (oParent.isDict()) + { + if (oParent.dictLookup("Ff", &oFT)->isInt()) + { + nFf = oFT.getInt(); + break; + } + oFT.free(); + oParent.dictLookup("Parent", &oParent2); + oParent.free(); + oParent = oParent2; + } + oParent.free(); + } + + bPushButton = (bool)((nFf >> 16) & 1); + if (bPushButton) + pAnnot = new PdfWriter::CPushButtonWidget(pXref); + else + pAnnot = new PdfWriter::CCheckBoxWidget(pXref); + } else if (strcmp("Tx", sName) == 0) pAnnot = new PdfWriter::CTextWidget(pXref); else if (strcmp("Ch", sName) == 0) @@ -2132,7 +2162,7 @@ HRESULT CPdfFile::AdvancedCommand(IAdvancedCommand* command) CWidgetsInfo* pCommand = (CWidgetsInfo*)command; #ifndef BUILDING_WASM_MODULE if (m_pInternal->bEdit && EditWidgets(pCommand)) - return m_pInternal->pWriter->EditWidgetParents(pCommand); + return m_pInternal->pWriter->EditWidgetParents(m_pInternal->pAppFonts, pCommand, m_pInternal->wsTempFolder); #endif return S_OK; } diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index c65d2c8930..9ed19d7d1c 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -1742,10 +1742,14 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF break; } case 27: + { + pAnnot = m_pDocument->CreatePushButtonWidget(); + break; + } case 28: case 29: { - pAnnot = m_pDocument->CreateButtonWidget(); + pAnnot = m_pDocument->CreateCheckBoxWidget(); break; } case 30: @@ -2151,27 +2155,17 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (oInfo.IsButtonWidget()) { - CAnnotFieldInfo::CWidgetAnnotPr::CButtonWidgetPr* pPr = oInfo.GetWidgetAnnotPr()->GetButtonWidgetPr(); - PdfWriter::CButtonWidget* pButtonWidget = (PdfWriter::CButtonWidget*)pAnnot; - - if (nFlags & (1 << 14)) - pButtonWidget->SetAP_N_Yes(pPr->GetAP_N_Yes()); - std::wstring wsValue; - if (nFlags & (1 << 9)) + if (nWidgetType == 27) { - wsValue = pPr->GetV(); - pButtonWidget->SetV(wsValue); - } + CAnnotFieldInfo::CWidgetAnnotPr::CButtonWidgetPr* pPr = oInfo.GetWidgetAnnotPr()->GetButtonWidgetPr(); + PdfWriter::CPushButtonWidget* pButtonWidget = (PdfWriter::CPushButtonWidget*)pAnnot; - if (nWidgetType == 27) // button - { if (nFlags & (1 << 10)) pButtonWidget->SetCA(pPr->GetCA()); if (nFlags & (1 << 11)) pButtonWidget->SetRC(pPr->GetRC()); if (nFlags & (1 << 12)) pButtonWidget->SetAC(pPr->GetAC()); - if (nFlags & (1 << 13)) pButtonWidget->SetTP(pPr->GetTP()); @@ -2190,12 +2184,29 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF pButtonWidget->SetA(d1, d2); } } + + if (nIFFlags & (1 << 5)) + pButtonWidget->SetI(pPr->GetI()); + if (nIFFlags & (1 << 6)) + pButtonWidget->SetRI(pPr->GetRI()); + if (nIFFlags & (1 << 7)) + pButtonWidget->SetIX(pPr->GetIX()); } - else // radiobutton и checkbox + else { + CAnnotFieldInfo::CWidgetAnnotPr::CButtonWidgetPr* pPr = oInfo.GetWidgetAnnotPr()->GetButtonWidgetPr(); + PdfWriter::CCheckBoxWidget* pButtonWidget = (PdfWriter::CCheckBoxWidget*)pAnnot; + + pButtonWidget->SetSubtype(nWidgetType); + if (nFlags & (1 << 14)) + pButtonWidget->SetAP_N_Yes(pPr->GetAP_N_Yes()); + if (nFlags & (1 << 9)) + pButtonWidget->SetV(pPr->GetV()); + std::wstring wsValue = pButtonWidget->SetStyle(pPr->GetStyle()); // ВНЕШНИЙ ВИД + // Если изменился текущий внешний вид if (pButtonWidget->Get("AP") && !wsValue.empty()) { pButtonWidget->SwitchAP(U_TO_UTF8(wsValue)); @@ -2205,7 +2216,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF double dMargin = 2; double dBaseLine = dY2 - dY1 - dFontSize - dMargin; // TODO цвет шрифта - pButtonWidget->SetAP(wsValue, m_pFont, {}, dFontSize, 0, dBaseLine); + pButtonWidget->SetAP(wsValue, m_pFont, dFontSize, 0, dBaseLine); } } else if (oInfo.IsTextWidget()) @@ -2382,7 +2393,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF double dBaseLine = dY2 - dY1 - dFontSize - dMargin; // TODO -BaseLineOffset // TODO цвет шрифта - pTextWidget->SetAP(wsValue, pCodes, unLen, m_pFont, {}, 1.0, m_oFont.GetSize(), dShiftX, dBaseLine, ppFonts, pShifts); + pTextWidget->SetAP(wsValue, pCodes, unLen, m_pFont, 1.0, m_oFont.GetSize(), dShiftX, dBaseLine, ppFonts, pShifts); RELEASEARRAYOBJECTS(pShifts); } @@ -2470,7 +2481,7 @@ HRESULT CPdfWriter::DrawImageWith1bppMask(IGrObject* pImage, NSImages::CPixJbig2 m_pPage->GrRestore(); return S_OK; } -HRESULT CPdfWriter::EditWidgetParents(CWidgetsInfo* pFieldInfo) +HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWidgetsInfo* pFieldInfo, const std::wstring& wsTempDirectory) { if (!m_pDocument || 0 == m_pDocument->GetPagesCount() || !pFieldInfo) return S_OK; @@ -2499,7 +2510,13 @@ HRESULT CPdfWriter::EditWidgetParents(CWidgetsInfo* pFieldInfo) PdfWriter::CArrayObject* pAKids = (PdfWriter::CArrayObject*)pKids; for (int i = 0; i < pAKids->GetCount(); ++i) { - PdfWriter::CButtonWidget* pKid = dynamic_cast(pAKids->Get(i)); + PdfWriter::CObjectBase* pObj = pAKids->Get(i); + if (pObj->GetType() != PdfWriter::object_type_DICT || + ((PdfWriter::CDictObject*)pObj)->GetDictType() != PdfWriter::dict_type_ANNOTATION || + ((PdfWriter::CAnnotation*)pObj)->GetAnnotationType() != PdfWriter::AnnotWidget || + ((PdfWriter::CWidgetAnnotation*)pObj)->GetWidgetType() != PdfWriter::WidgetCheckbox) + continue; + PdfWriter::CCheckBoxWidget* pKid = dynamic_cast(pObj); if (pKid) pKid->SwitchAP(sV); } @@ -2515,6 +2532,45 @@ HRESULT CPdfWriter::EditWidgetParents(CWidgetsInfo* pFieldInfo) } } + std::vector arrBI = pFieldInfo->GetButtonImg(); + std::vector arrImg; + for (int i = 0; i < arrBI.size(); ++i) + { + std::wstring wsPath = arrBI[i]; + if (wsPath.empty()) + { + arrImg.push_back(NULL); + continue; + } + + Aggplus::CImage* pCImage = NULL; + CImageFileFormatChecker oImageFormat(wsPath); + if (_CXIMAGE_FORMAT_WMF == oImageFormat.eFileType || + _CXIMAGE_FORMAT_EMF == oImageFormat.eFileType || + _CXIMAGE_FORMAT_SVM == oImageFormat.eFileType || + _CXIMAGE_FORMAT_SVG == oImageFormat.eFileType) + { + MetaFile::IMetaFile* pMeta = MetaFile::Create(pAppFonts); + pMeta->LoadFromFile(wsPath.c_str()); + + double dNewW = 10.0 / 25.4 * 300; + std::wstring wsTempFile = GetTempFile(wsTempDirectory); + pMeta->ConvertToRaster(wsTempFile.c_str(), _CXIMAGE_FORMAT_PNG, dNewW); + + RELEASEOBJECT(pMeta); + + pCImage = new Aggplus::CImage(wsTempFile); + } + else + pCImage = new Aggplus::CImage(wsPath); + + PdfWriter::CImageDict* pImage = LoadImage(pCImage, 255); + RELEASEOBJECT(pCImage); + + arrImg.push_back(pImage); + } + m_pDocument->UpdateButtonImg(arrImg); + return S_OK; } bool CPdfWriter::EditPage(PdfWriter::CPage* pNewPage) diff --git a/PdfFile/PdfWriter.h b/PdfFile/PdfWriter.h index 1d4c213c1b..df6d1b0a3a 100644 --- a/PdfFile/PdfWriter.h +++ b/PdfFile/PdfWriter.h @@ -214,7 +214,7 @@ public: bool EditClose(); void PageRotate(int nRotate); void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate); - HRESULT EditWidgetParents(CWidgetsInfo* pFieldInfo); + HRESULT EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWidgetsInfo* pFieldInfo, const std::wstring& wsTempDirectory); PdfWriter::CDocument* m_pDocument; PdfWriter::CPage* m_pPage; diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index c89e106373..4320fb24c0 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -2673,31 +2673,36 @@ void CAnnotWidgetBtn::ToWASM(NSWasm::CData& oRes) if (m_unFlags & (1 << 9)) oRes.WriteString(m_sV); - oRes.AddInt(m_unIFFlag); if (m_nType == 27) { + oRes.AddInt(m_unIFFlag); if (m_unFlags & (1 << 10)) oRes.WriteString(m_sCA); if (m_unFlags & (1 << 11)) oRes.WriteString(m_sRC); if (m_unFlags & (1 << 12)) oRes.WriteString(m_sAC); + if (m_unFlags & (1 << 13)) + oRes.WriteBYTE(m_nTP); + if (m_unIFFlag & (1 << 0)) + { + if (m_unIFFlag & (1 << 1)) + oRes.WriteBYTE(m_nSW); + if (m_unIFFlag & (1 << 2)) + oRes.WriteBYTE(m_nS); + if (m_unIFFlag & (1 << 3)) + { + oRes.AddDouble(m_dA1); + oRes.AddDouble(m_dA2); + } + } } else - oRes.WriteBYTE(m_nStyle); - if (m_unFlags & (1 << 13)) - oRes.WriteBYTE(m_nTP); - if (m_unIFFlag & (1 << 1)) - oRes.WriteBYTE(m_nSW); - if (m_unIFFlag & (1 << 2)) - oRes.WriteBYTE(m_nS); - if (m_unIFFlag & (1 << 3)) { - oRes.AddDouble(m_dA1); - oRes.AddDouble(m_dA2); + oRes.WriteBYTE(m_nStyle); + if (m_unFlags & (1 << 14)) + oRes.WriteString(m_sAP_N_Yes); } - if (m_unFlags & (1 << 14)) - oRes.WriteString(m_sAP_N_Yes); } void CAnnotWidgetTx::ToWASM(NSWasm::CData& oRes) diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index 002525b9f9..c8e582e59d 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -34,6 +34,7 @@ #include "Utils.h" #include "ResourcesDictionary.h" #include "Streams.h" +#include "Image.h" #include "../../DesktopEditor/common/File.h" @@ -1002,15 +1003,23 @@ namespace PdfWriter return GetColor(m_arrBC, true) + "\012"; } //---------------------------------------------------------------------------------------- - // CButtonWidget + // CPushButtonWidget //---------------------------------------------------------------------------------------- - CButtonWidget::CButtonWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget) + CPushButtonWidget::CPushButtonWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget) { Add("FT", "Btn"); m_pIF = NULL; + m_nI = -1; + m_nRI = -1; + m_nIX = -1; + m_nScaleType = 0; + m_bRespectBorders = false; + m_bConstantProportions = true; + m_dShiftX = 0.5; + m_dShiftY = 0.5; } - void CButtonWidget::CheckIF() + void CPushButtonWidget::CheckIF() { CheckMK(); @@ -1020,7 +1029,7 @@ namespace PdfWriter m_pMK->Add("IF", m_pIF); } } - void CButtonWidget::SetV(const std::wstring& wsV) + void CPushButtonWidget::SetV(const std::wstring& wsV) { std::string sV = U_TO_UTF8(wsV); CDictObject* pOwner = GetObjOwnValue("V"); @@ -1030,13 +1039,15 @@ namespace PdfWriter pOwner = this; pOwner->Add("V", new CStringObject(sV.c_str(), true)); } - void CButtonWidget::SetDV(const std::wstring& wsDV) + void CPushButtonWidget::SetDV(const std::wstring& wsDV) { std::string sValue = U_TO_UTF8(wsDV); Add("DV", sValue.c_str()); } - void CButtonWidget::SetS(const BYTE& nS) + void CPushButtonWidget::SetS(const BYTE& nS) { + m_bConstantProportions = !nS; + CheckIF(); std::string sValue; @@ -1051,12 +1062,14 @@ namespace PdfWriter m_pIF->Add("S", sValue.c_str()); } - void CButtonWidget::SetTP(const BYTE& nTP) + void CPushButtonWidget::SetTP(const BYTE& nTP) { Add("TP", (int)nTP); } - void CButtonWidget::SetSW(const BYTE& nSW) + void CPushButtonWidget::SetSW(const BYTE& nSW) { + m_nScaleType = nSW; + CheckIF(); std::string sValue; @@ -1075,7 +1088,212 @@ namespace PdfWriter m_pIF->Add("SW", sValue.c_str()); } - std::wstring CButtonWidget::SetStyle(const BYTE& nStyle) + void CPushButtonWidget::SetIFFlag(const int& nIFFlag) + { + CheckIF(); + + m_bRespectBorders = (nIFFlag & (1 << 4)) ? false : true; + m_pIF->Add("FB", !m_bRespectBorders); + } + void CPushButtonWidget::SetI(const int& nI) + { + m_nI = nI; + } + void CPushButtonWidget::SetRI(const int& nRI) + { + m_nRI = nRI; + } + void CPushButtonWidget::SetIX(const int& nIX) + { + m_nIX = nIX; + } + void CPushButtonWidget::SetA(const double& dA1, const double& dA2) + { + m_dShiftX = dA1; + m_dShiftY = dA2; + + CheckIF(); + + CArrayObject* pArray = new CArrayObject(); + if (!pArray) + return; + + m_pIF->Add("A", pArray); + + pArray->Add(dA1); + pArray->Add(dA2); + } + void CPushButtonWidget::SetCA(const std::wstring& wsCA) + { + CheckMK(); + + std::string sValue = U_TO_UTF8(wsCA); + m_pMK->Add("CA", new CStringObject(sValue.c_str())); + } + void CPushButtonWidget::SetRC(const std::wstring& wsRC) + { + CheckMK(); + + std::string sValue = U_TO_UTF8(wsRC); + m_pMK->Add("RC", new CStringObject(sValue.c_str())); + } + void CPushButtonWidget::SetAC(const std::wstring& wsAC) + { + CheckMK(); + + std::string sValue = U_TO_UTF8(wsAC); + m_pMK->Add("AC", new CStringObject(sValue.c_str())); + } + void CPushButtonWidget::SetAP(CImageDict* pImage) + { + CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this); + Add("AP", pAppearance); + + CAnnotAppearanceObject* pNormal = pAppearance->GetNormal(); + CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources(); + + std::string sDA = "0.909 0.941 0.992 rg"; + Add("DA", new CStringObject(sDA.c_str())); + + if (pImage) + { + TRect oRect = GetRect(); + + double dH = fabs(oRect.fTop - oRect.fBottom); + double dW = fabs(oRect.fRight - oRect.fLeft); + + // TODO нужно ли преобразование? + double dOriginW = pImage->GetWidth() * 72 / 96.0; + double dOriginH = pImage->GetHeight() * 72 / 96.0; + + bool bNeedScale = (0 == m_nScaleType + || (2 == m_nScaleType && (dOriginH > dH || dOriginW > dW)) + || (3 == m_nScaleType && dOriginH < dH && dOriginW < dW)); + + double dDstW = dOriginW; + double dDstH = dOriginH; + double dDstX = 0; + double dDstY = 0; + + if (m_bRespectBorders && HaveBorder()) + { + double dBorderSize = GetBorderWidth(); + dDstX += 2 * dBorderSize; + dDstY += 2 * dBorderSize; + dH -= 4 * dBorderSize; + dW -= 4 * dBorderSize; + } + + if (bNeedScale) + { + if (!m_bConstantProportions) + { + dDstH = dH; + dDstW = dW; + } + else + { + double dScaleKoef = fmin(dW / dOriginW, dH / dOriginH); + dDstW = dScaleKoef * dOriginW; + dDstH = dScaleKoef * dOriginH; + } + } + + dDstX += (dW - dDstW) * m_dShiftX; + dDstY += (dH - dDstH) * m_dShiftY; + + CXObject* pForm = new CXObject(); + CStream* pStream = new CMemoryStream(); + pForm->SetStream(m_pXref, pStream); + +#ifndef FILTER_FLATE_DECODE_DISABLED + if (m_pDocument->GetCompressionMode() & COMP_TEXT) + pForm->SetFilter(STREAM_FILTER_FLATE_DECODE); +#endif + CArrayObject* pBBox = new CArrayObject(); + pForm->Add("BBox", pBBox); + pBBox->Add(0); + pBBox->Add(0); + pBBox->Add(dOriginW); + pBBox->Add(dOriginH); + pForm->Add("FormType", 1); + CArrayObject* pFormMatrix = new CArrayObject(); + pForm->Add("Matrix", pFormMatrix); + pFormMatrix->Add(1); + pFormMatrix->Add(0); + pFormMatrix->Add(0); + pFormMatrix->Add(1); + pFormMatrix->Add(0); + pFormMatrix->Add(0); + pForm->Add("Name", "FRM"); + + CDictObject* pFormRes = new CDictObject(); + CArrayObject* pFormResProcset = new CArrayObject(); + pFormRes->Add("ProcSet", pFormResProcset); + pFormResProcset->Add(new CNameObject("PDF")); + pFormResProcset->Add(new CNameObject("ImageC")); + CDictObject* pFormResXObject = new CDictObject(); + pFormRes->Add("XObject", pFormResXObject); + pFormResXObject->Add("Img", pImage); + pForm->Add("Resources", pFormRes); + + pForm->Add("Subtype", "Form"); + pForm->Add("Type", "XObject"); + + pStream->WriteStr("q\012"); + pStream->WriteReal(dOriginW); + pStream->WriteStr(" 0 0 "); + pStream->WriteReal(dOriginH); + pStream->WriteStr(" 0 0 cm\012/Img Do\012Q"); + + pFieldsResources->AddXObjectWithName("FRM", pForm); + pNormal->DrawPicture("FRM", dDstX, dDstY, dDstW / dOriginW, dDstH / dOriginH, m_bRespectBorders); + } + else + { + pNormal->DrawPicture(); + } + } + void CPushButtonWidget::SetI(CImageDict* pI) + { + SetAP(pI); + } + void CPushButtonWidget::SetRI(CImageDict* pI) + { + SetAP(pI); + } + void CPushButtonWidget::SetIX(CImageDict* pI) + { + SetAP(pI); + } + //---------------------------------------------------------------------------------------- + // CCheckBoxWidget + //---------------------------------------------------------------------------------------- + CCheckBoxWidget::CCheckBoxWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget) + { + Add("FT", "Btn"); + m_nSubtype = WidgetRadiobutton; + } + void CCheckBoxWidget::SetV(const std::wstring& wsV) + { + std::string sV = U_TO_UTF8(wsV); + CDictObject* pOwner = GetObjOwnValue("V"); + if (!pOwner) + pOwner = GetObjOwnValue("FT"); + if (!pOwner) + pOwner = this; + pOwner->Add("V", new CStringObject(sV.c_str(), true)); + } + void CCheckBoxWidget::SetDV(const std::wstring& wsDV) + { + std::string sValue = U_TO_UTF8(wsDV); + Add("DV", sValue.c_str()); + } + void CCheckBoxWidget::SetSubtype(const BYTE& nSubtype) + { + m_nSubtype = (EWidgetType)nSubtype; + } + std::wstring CCheckBoxWidget::SetStyle(const BYTE& nStyle) { CheckMK(); @@ -1101,56 +1319,16 @@ namespace PdfWriter return UTF8_TO_U(sValue); } - void CButtonWidget::SetIFFlag(const int& nIFFlag) - { - CheckIF(); - - m_pIF->Add("FB", (nIFFlag & (1 << 4)) ? true : false); - } - void CButtonWidget::SetA(const double& dA1, const double& dA2) - { - CheckIF(); - - CArrayObject* pArray = new CArrayObject(); - if (!pArray) - return; - - m_pIF->Add("A", pArray); - - pArray->Add(dA1); - pArray->Add(dA2); - } - void CButtonWidget::SetCA(const std::wstring& wsCA) - { - CheckMK(); - - std::string sValue = U_TO_UTF8(wsCA); - m_pMK->Add("CA", new CStringObject(sValue.c_str())); - } - void CButtonWidget::SetRC(const std::wstring& wsRC) - { - CheckMK(); - - std::string sValue = U_TO_UTF8(wsRC); - m_pMK->Add("RC", new CStringObject(sValue.c_str())); - } - void CButtonWidget::SetAC(const std::wstring& wsAC) - { - CheckMK(); - - std::string sValue = U_TO_UTF8(wsAC); - m_pMK->Add("AC", new CStringObject(sValue.c_str())); - } - void CButtonWidget::SetAP_N_Yes(const std::wstring& wsAP_N_Yes) + void CCheckBoxWidget::SetAP_N_Yes(const std::wstring& wsAP_N_Yes) { std::string sValue = U_TO_UTF8(wsAP_N_Yes); m_sAP_N_Yes = sValue; } - void CButtonWidget::SwitchAP(const std::string& sV) + void CCheckBoxWidget::SwitchAP(const std::string& sV) { Add("AS", sV == m_sAP_N_Yes ? sV.c_str() : "Off"); } - void CButtonWidget::SetAP(const std::wstring& wsValue, CFontDict* pFont, const TRgb& oColor, double dFontSize, double dX, double dY) + void CCheckBoxWidget::SetAP(const std::wstring& wsValue, CFontDict* pFont, double dFontSize, double dX, double dY) { m_pAppearance = new CAnnotAppearance(m_pXref, this); if (!m_pAppearance) @@ -1159,7 +1337,7 @@ namespace PdfWriter CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal(); - pNormal->DrawSimpleText(wsValue, NULL, 0, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, NULL, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop), NULL, NULL); + pNormal->DrawSimpleText(wsValue, NULL, 0, pFont, dFontSize, dX, dY, 0, 0, 0, NULL, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop), NULL, NULL); } //---------------------------------------------------------------------------------------- // CTextWidget @@ -1192,7 +1370,7 @@ namespace PdfWriter std::string sValue = U_TO_UTF8(wsRV); Add("RV", new CStringObject(sValue.c_str())); } - void CTextWidget::SetAP(const std::wstring& wsValue, unsigned short* pCodes, unsigned int unCount, CFontDict* pFont, const TRgb& oColor, const double& dAlpha, double dFontSize, double dX, double dY, CFontCidTrueType** ppFonts, double* pShifts) + void CTextWidget::SetAP(const std::wstring& wsValue, unsigned short* pCodes, unsigned int unCount, CFontDict* pFont, const double& dAlpha, double dFontSize, double dX, double dY, CFontCidTrueType** ppFonts, double* pShifts) { m_pAppearance = new CAnnotAppearance(m_pXref, this); if (!m_pAppearance) @@ -1209,7 +1387,7 @@ namespace PdfWriter sExtGrStateName = pFieldsResources->GetExtGrStateName(pExtGrState); } - pNormal->DrawSimpleText(wsValue, pCodes, unCount, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop), ppFonts, pShifts); + pNormal->DrawSimpleText(wsValue, pCodes, unCount, pFont, dFontSize, dX, dY, 0, 0, 0, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop), ppFonts, pShifts); } void CTextWidget::StartAP(CFontDict* pFont, const double& dFontSize, const double& dAlpha) { diff --git a/PdfFile/SrcWriter/Annotation.h b/PdfFile/SrcWriter/Annotation.h index 3f4cfa2e67..95b915b32b 100644 --- a/PdfFile/SrcWriter/Annotation.h +++ b/PdfFile/SrcWriter/Annotation.h @@ -354,6 +354,14 @@ namespace PdfWriter public: CWidgetAnnotation(CXref* pXref, EAnnotType eType); + EAnnotType GetAnnotationType() const override + { + return AnnotWidget; + } + virtual EWidgetType GetWidgetType() const + { + return WidgetUnknown; + } void SetDA(CFontDict* pFont, const double& dFontSize, const double& dFontSizeAP, const std::vector& arrTC); CDictObject* GetObjOwnValue(const std::string& sV); @@ -376,20 +384,23 @@ namespace PdfWriter std::string GetBGforAP(); std::string GetBCforAP(); }; - class CButtonWidget : public CWidgetAnnotation + class CPushButtonWidget : public CWidgetAnnotation { private: - EAnnotType m_nSubtype; + bool m_bRespectBorders; + bool m_bConstantProportions; + BYTE m_nScaleType; + double m_dShiftX; + double m_dShiftY; CDictObject* m_pIF; - std::string m_sAP_N_Yes; void CheckIF(); public: - CButtonWidget(CXref* pXref); - EAnnotType GetAnnotationType() const override + CPushButtonWidget(CXref* pXref); + virtual EWidgetType GetWidgetType() const override { - return m_nSubtype; + return WidgetPushbutton; } void SetV(const std::wstring& wsV); @@ -397,16 +408,42 @@ namespace PdfWriter void SetS(const BYTE& nS); void SetTP(const BYTE& nTP); void SetSW(const BYTE& nSW); - std::wstring SetStyle(const BYTE& nStyle); void SetIFFlag(const int& nIFFlag); + void SetI(const int& nI); + void SetRI(const int& nRI); + void SetIX(const int& nIX); void SetA(const double& dA1, const double& dA2); void SetCA(const std::wstring& wsCA); void SetRC(const std::wstring& wsRC); void SetAC(const std::wstring& wsAC); + void SetI(CImageDict* pI); + void SetRI(CImageDict* pRI); + void SetIX(CImageDict* pIX); + + void SetAP(CImageDict* pImage); + int m_nI, m_nRI, m_nIX; + }; + class CCheckBoxWidget : public CWidgetAnnotation + { + private: + EWidgetType m_nSubtype; + std::string m_sAP_N_Yes; + + public: + CCheckBoxWidget(CXref* pXref); + virtual EWidgetType GetWidgetType() const override + { + return m_nSubtype; + } + + void SetV(const std::wstring& wsV); + void SetDV(const std::wstring& wsDV) override; + void SetSubtype(const BYTE& nSubtype); + std::wstring SetStyle(const BYTE& nStyle); void SetAP_N_Yes(const std::wstring& wsAP_N_Yes); void SwitchAP(const std::string& sV); - void SetAP(const std::wstring& wsValue, CFontDict* pFont, const TRgb& oColor, double dFontSize, double dX, double dY); + void SetAP(const std::wstring& wsValue, CFontDict* pFont, double dFontSize, double dX, double dY); }; class CTextWidget : public CWidgetAnnotation { @@ -416,16 +453,12 @@ namespace PdfWriter public: CTextWidget(CXref* pXref); - EAnnotType GetAnnotationType() const override - { - return m_nSubtype; - } void SetMaxLen(const int& nMaxLen); void SetV (const std::wstring& wsV); void SetRV(const std::wstring& wsRV); - void SetAP(const std::wstring& wsValue, unsigned short* pCodes, unsigned int unCount, CFontDict* pFont, const TRgb& oColor, const double& dAlpha, double dFontSize, double dX, double dY, CFontCidTrueType** ppFonts, double* pShifts); + void SetAP(const std::wstring& wsValue, unsigned short* pCodes, unsigned int unCount, CFontDict* pFont, const double& dAlpha, double dFontSize, double dX, double dY, CFontCidTrueType** ppFonts, double* pShifts); void StartAP(CFontDict* pFont, const double& dFontSize, const double& dAlpha); void AddLineToAP(const double& dX, const double& dY, unsigned short* pCodes, const unsigned int& unCodesCount, CFontCidTrueType** ppFonts = NULL, const double* pShifts = NULL); void EndAP(); @@ -441,10 +474,6 @@ namespace PdfWriter public: CChoiceWidget(CXref* pXref); - EAnnotType GetAnnotationType() const override - { - return m_nSubtype; - } void SetTI(const int& nTI); void SetV(const std::wstring& wsV); diff --git a/PdfFile/SrcWriter/Document.cpp b/PdfFile/SrcWriter/Document.cpp index 3240ebe131..b4519de3f8 100644 --- a/PdfFile/SrcWriter/Document.cpp +++ b/PdfFile/SrcWriter/Document.cpp @@ -630,9 +630,13 @@ namespace PdfWriter return pWidget; } - CAnnotation* CDocument::CreateButtonWidget() + CAnnotation* CDocument::CreatePushButtonWidget() { - return new CButtonWidget(m_pXref); + return new CPushButtonWidget(m_pXref); + } + CAnnotation* CDocument::CreateCheckBoxWidget() + { + return new CCheckBoxWidget(m_pXref); } CAnnotation* CDocument::CreateTextWidget() { @@ -1402,8 +1406,6 @@ namespace PdfWriter m_pAcroForm->Add("CO", pArray); - - for (int CO : arrCO) { CDictObject* pObj = GetParent(CO); @@ -1454,6 +1456,23 @@ namespace PdfWriter return true; } + void CDocument::UpdateButtonImg(const std::vector& arrButtonImg) + { + for (auto it = m_mAnnotations.begin(); it != m_mAnnotations.end(); it++) + { + CAnnotation* pAnnot = it->second; + if (pAnnot->GetAnnotationType() != AnnotWidget || ((CWidgetAnnotation*)pAnnot)->GetWidgetType() != WidgetPushbutton) + continue; + + CPushButtonWidget* pPBWidget = (CPushButtonWidget*)pAnnot; + if (pPBWidget->m_nI >= 0) + pPBWidget->SetI(arrButtonImg[pPBWidget->m_nI]); + if (pPBWidget->m_nRI >= 0) + pPBWidget->SetRI(arrButtonImg[pPBWidget->m_nRI]); + if (pPBWidget->m_nIX >= 0) + pPBWidget->SetIX(arrButtonImg[pPBWidget->m_nIX]); + } + } CPage* CDocument::AddPage(int nPageIndex) { if (!m_pPageTree) diff --git a/PdfFile/SrcWriter/Document.h b/PdfFile/SrcWriter/Document.h index c135dd70a6..1dc6b80479 100644 --- a/PdfFile/SrcWriter/Document.h +++ b/PdfFile/SrcWriter/Document.h @@ -145,7 +145,8 @@ namespace PdfWriter CAnnotation* CreateFreeTextAnnot(); CAnnotation* CreateCaretAnnot(); CAnnotation* CreateWidgetAnnot(); - CAnnotation* CreateButtonWidget(); + CAnnotation* CreatePushButtonWidget(); + CAnnotation* CreateCheckBoxWidget(); CAnnotation* CreateTextWidget(); CAnnotation* CreateChoiceWidget(); CAnnotation* CreateSignatureWidget(); @@ -192,6 +193,7 @@ namespace PdfWriter CPage* GetCurPage() { return m_pCurPage; } void SetCurPage(CPage* pPage) { m_pCurPage = pPage; } bool EditCO(const std::vector& arrCO); + void UpdateButtonImg(const std::vector& arrButtonImg); private: char* GetTTFontTag(); diff --git a/PdfFile/SrcWriter/Field.h b/PdfFile/SrcWriter/Field.h index de1de2f5ed..74ef92c0bd 100644 --- a/PdfFile/SrcWriter/Field.h +++ b/PdfFile/SrcWriter/Field.h @@ -81,6 +81,17 @@ namespace PdfWriter AnnotCaret = 17, AnnotWidget = 18 }; + enum EWidgetType + { + WidgetUnknown = 26, + WidgetPushbutton = 27, + WidgetRadiobutton = 28, + WidgetCheckbox = 29, + WidgetText = 30, + WidgetCombobox = 31, + WidgetListbox = 32, + WisgetSignature = 33 + }; enum EAnnotHighlightMode { AnnotNoHighlight = 0,