diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index 0ea825f455..a112b84890 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -645,10 +645,12 @@ void CAnnotFieldInfo::CCaretAnnotPr::Read(NSOnlineOfficeBinToPdf::CBufferReader* m_nSy = pReader->ReadByte(); } +int CAnnotFieldInfo::CStampAnnotPr::GetRotate() { return m_nRotate; } const std::wstring& CAnnotFieldInfo::CStampAnnotPr::GetName() { return m_wsName; } void CAnnotFieldInfo::CStampAnnotPr::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, int nFlags) { m_wsName = pReader->ReadString(); + m_nRotate = pReader->ReadInt(); } bool CAnnotFieldInfo::CPopupAnnotPr::IsOpen() const { return m_bOpen; } diff --git a/DesktopEditor/graphics/commands/AnnotField.h b/DesktopEditor/graphics/commands/AnnotField.h index c1cafb8873..548101ac89 100644 --- a/DesktopEditor/graphics/commands/AnnotField.h +++ b/DesktopEditor/graphics/commands/AnnotField.h @@ -402,11 +402,13 @@ public: class GRAPHICS_DECL CStampAnnotPr { public: + int GetRotate(); const std::wstring& GetName(); void Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, int nFlags); private: + int m_nRotate; std::wstring m_wsName; }; diff --git a/PdfFile/PdfEditor.cpp b/PdfFile/PdfEditor.cpp index 5f35b77306..5f0188215c 100644 --- a/PdfFile/PdfEditor.cpp +++ b/PdfFile/PdfEditor.cpp @@ -1111,6 +1111,44 @@ bool CPdfEditor::EditAnnot(int nPageIndex, int nID) } else if (oType.isName("Caret")) pAnnot = new PdfWriter::CCaretAnnotation(pXref); + else if (oType.isName("Stamp")) + { + pAnnot = new PdfWriter::CStampAnnotation(pXref); + + Object oAP, oAPN; + if (oAnnot.dictLookup("AP", &oAP)->isDict() && oAP.dictLookup("N", &oAPN)->isStream()) + { + Object oObj; + Dict* pAPN = oAPN.streamGetDict(); + if (pAPN->lookup("BBox", &oObj)->isArray() && oObj.arrayGetLength() == 4) + { + double d[4]; + for (int i = 0; i < 4; ++i) + { + Object oObj2; + oObj.arrayGet(i, &oObj2); + d[i] = oObj2.getNum(); + oObj2.free(); + } + ((PdfWriter::CStampAnnotation*)pAnnot)->SetBBox({ d[0], d[1], d[2], d[3] }); + } + oObj.free(); + if (pAPN->lookup("Matrix", &oObj)->isArray() && oObj.arrayGetLength() == 6) + { + double d[6]; + for (int i = 0; i < 6; ++i) + { + Object oObj2; + oObj.arrayGet(i, &oObj2); + d[i] = oObj2.getNum(); + oObj2.free(); + } + ((PdfWriter::CStampAnnotation*)pAnnot)->SetMatrix({ d[0], d[1], d[2], d[3], d[4], d[5] }); + } + oObj.free(); + } + oAP.free(); oAPN.free(); + } else if (oType.isName("Popup")) pAnnot = new PdfWriter::CPopupAnnotation(pXref); else if (oType.isName("Widget")) diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index a93b258712..3f822c3395 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -1902,10 +1902,10 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (nFlags & (1 << 7)) pMarkupAnnot->SetSubj(pPr->GetSubj()); - pMarkupAnnot->RemoveAP(); - if (oInfo.IsText()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CTextAnnotPr* pPr = oInfo.GetTextAnnotPr(); PdfWriter::CTextAnnotation* pTextAnnot = (PdfWriter::CTextAnnotation*)pAnnot; @@ -1921,6 +1921,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsInk()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CInkAnnotPr* pPr = oInfo.GetInkAnnotPr(); PdfWriter::CInkAnnotation* pInkAnnot = (PdfWriter::CInkAnnotation*)pAnnot; @@ -1934,6 +1936,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsLine()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CLineAnnotPr* pPr = oInfo.GetLineAnnotPr(); PdfWriter::CLineAnnotation* pLineAnnot = (PdfWriter::CLineAnnotation*)pAnnot; @@ -1977,6 +1981,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsTextMarkup()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CTextMarkupAnnotPr* pPr = oInfo.GetTextMarkupAnnotPr(); PdfWriter::CTextMarkupAnnotation* pTextMarkupAnnot = (PdfWriter::CTextMarkupAnnotation*)pAnnot; @@ -1985,6 +1991,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsSquareCircle()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CSquareCircleAnnotPr* pPr = oInfo.GetSquareCircleAnnotPr(); PdfWriter::CSquareCircleAnnotation* pSquareCircleAnnot = (PdfWriter::CSquareCircleAnnotation*)pAnnot; @@ -2006,6 +2014,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsPolygonLine()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CPolygonLineAnnotPr* pPr = oInfo.GetPolygonLineAnnotPr(); PdfWriter::CPolygonLineAnnotation* pPolygonLineAnnot = (PdfWriter::CPolygonLineAnnotation*)pAnnot; @@ -2030,6 +2040,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsFreeText()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CFreeTextAnnotPr* pFTPr = oInfo.GetFreeTextAnnotPr(); PdfWriter::CFreeTextAnnotation* pFreeTextAnnot = (PdfWriter::CFreeTextAnnotation*)pAnnot; @@ -2069,6 +2081,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } else if (oInfo.IsCaret()) { + pMarkupAnnot->RemoveAP(); + CAnnotFieldInfo::CCaretAnnotPr* pPr = oInfo.GetCaretAnnotPr(); PdfWriter::CCaretAnnotation* pCaretAnnot = (PdfWriter::CCaretAnnotation*)pAnnot; @@ -2087,6 +2101,9 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF PdfWriter::CStampAnnotation* pStampAnnot = (PdfWriter::CStampAnnotation*)pAnnot; pStampAnnot->SetName(pPr->GetName()); + pStampAnnot->SetRotate(pPr->GetRotate()); + + pStampAnnot->SetAP(); } } else if (oInfo.IsPopup()) diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index a001db8004..3a1c0eeb7e 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -1343,14 +1343,135 @@ namespace PdfWriter //---------------------------------------------------------------------------------------- // CStampAnnotation //---------------------------------------------------------------------------------------- - CStampAnnotation::CStampAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotStamp) + CStampAnnotation::CStampAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotStamp), m_oBeforeRect(0, 0, 0, 0), m_nDiffRotate(0) { } + void CStampAnnotation::SetRect(const TRect& oRect) + { + CObjectBase* pObj = Get("Rect"); + if (pObj->GetType() != object_type_ARRAY) + return; + CArrayObject* pRect = (CArrayObject*)pObj; + pObj = pRect->Get(0); + m_oBeforeRect.fLeft = pObj->GetType() == PdfWriter::object_type_NUMBER ? ((PdfWriter::CNumberObject*)pObj)->Get() : ((PdfWriter::CRealObject*)pObj)->Get(); + pObj = pRect->Get(1); + m_oBeforeRect.fBottom = pObj->GetType() == PdfWriter::object_type_NUMBER ? ((PdfWriter::CNumberObject*)pObj)->Get() : ((PdfWriter::CRealObject*)pObj)->Get(); + pObj = pRect->Get(2); + m_oBeforeRect.fRight = pObj->GetType() == PdfWriter::object_type_NUMBER ? ((PdfWriter::CNumberObject*)pObj)->Get() : ((PdfWriter::CRealObject*)pObj)->Get(); + pObj = pRect->Get(3); + m_oBeforeRect.fTop = pObj->GetType() == PdfWriter::object_type_NUMBER ? ((PdfWriter::CNumberObject*)pObj)->Get() : ((PdfWriter::CRealObject*)pObj)->Get(); + + CAnnotation::SetRect(oRect); + } + void CStampAnnotation::SetRotate(int nRotate) + { + CObjectBase* pObj = Get("Rotate"); + if (pObj->GetType() == object_type_NUMBER) + m_nDiffRotate = nRotate - ((CNumberObject*)pObj)->Get(); + //m_nDiffRotate = nRotate; + + Add("Rotate", nRotate); + } void CStampAnnotation::SetName(const std::wstring& wsName) { std::string sValue = U_TO_UTF8(wsName); Add("Name", sValue.c_str()); } + void CStampAnnotation::SetBBox(const TRect& oRect) + { + m_oBBox = oRect; + } + void CStampAnnotation::SetMatrix(const CMatrix& oMatrix) + { + m_oMatrix = oMatrix; + } + void CStampAnnotation::SetAP() + { + CObjectBase* pAPN = ((CDictObject*)Get("AP"))->Get("N"); + CObjectBase* pN = new CObjectBase(); + pN->SetRef(pAPN->GetObjId(), pAPN->GetGenNo()); + pN->SetIndirect(); + + CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this); + Add("AP", pAppearance); + CAnnotAppearanceObject* pNormal = pAppearance->GetNormal(); + CStream* pStream = pNormal->GetStream(); + + CResourcesDict* pResources = (CResourcesDict*)pNormal->Get("Resources"); + const char* sXObjectName = pResources->GetXObjectName(pN); + if (!sXObjectName) + return; + + CArrayObject* pArray = new CArrayObject(); + if (!pArray) + return; + pNormal->Add("BBox", pArray); + + double x, y, formXMin, formYMin, formXMax, formYMax; + x = m_oBBox.fLeft; + y = m_oBBox.fBottom; + m_oMatrix.Apply(x, y); + formXMin = formXMax = x; + formYMin = formYMax = y; + + x = m_oBBox.fLeft; + y = m_oBBox.fTop; + m_oMatrix.Apply(x, y); + if (x < formXMin) + formXMin = x; + else if (x > formXMax) + formXMax = x; + if (y < formYMin) + formYMin = y; + else if (y > formYMax) + formYMax = y; + + x = m_oBBox.fRight; + y = m_oBBox.fBottom; + m_oMatrix.Apply(x, y); + if (x < formXMin) + formXMin = x; + else if (x > formXMax) + formXMax = x; + if (y < formYMin) + formYMin = y; + else if (y > formYMax) + formYMax = y; + + x = m_oBBox.fRight; + y = m_oBBox.fTop; + m_oMatrix.Apply(x, y); + if (x < formXMin) + formXMin = x; + else if (x > formXMax) + formXMax = x; + if (y < formYMin) + formYMin = y; + else if (y > formYMax) + formYMax = y; + + pArray->Add(formXMin); + pArray->Add(formYMin); + pArray->Add(formXMax); + pArray->Add(formYMax); + + pArray = new CArrayObject(); + if (!pArray) + return; + + double ca = cos(m_nDiffRotate / 180.0 * M_PI); + double sa = sin(m_nDiffRotate / 180.0 * M_PI); + pNormal->Add("Matrix", pArray); + pArray->Add(ca); + pArray->Add(sa); + pArray->Add(-sa); + pArray->Add(ca); + pArray->Add(0); + pArray->Add(0); + + pStream->WriteEscapeName(sXObjectName); + pStream->WriteStr(" Do\012"); + } //---------------------------------------------------------------------------------------- // CWidgetAnnotation //---------------------------------------------------------------------------------------- diff --git a/PdfFile/SrcWriter/Annotation.h b/PdfFile/SrcWriter/Annotation.h index 8cd9de9793..94e54f60a7 100644 --- a/PdfFile/SrcWriter/Annotation.h +++ b/PdfFile/SrcWriter/Annotation.h @@ -172,7 +172,7 @@ namespace PdfWriter return false; } - void SetRect(const TRect& oRect); + virtual void SetRect(const TRect& oRect); void SetBorder(BYTE nType, double dWidth, const std::vector& arrDash); void SetAnnotFlag(const int& nAnnotFlag); void SetPage(CPage* pPage, double dW = 0, double dH = 0, double dX = 0); @@ -386,6 +386,11 @@ namespace PdfWriter }; class CStampAnnotation : public CMarkupAnnotation { + private: + TRect m_oBeforeRect; + TRect m_oBBox; + CMatrix m_oMatrix; + double m_nDiffRotate; public: CStampAnnotation(CXref* pXref); EAnnotType GetAnnotationType() const override @@ -393,7 +398,13 @@ namespace PdfWriter return AnnotStamp; } + virtual void SetRect(const TRect& oRect) override; + void SetRotate(int nRotate); void SetName(const std::wstring& wsName); + void SetBBox(const TRect& oRect); + void SetMatrix(const CMatrix& oMatrix); + + void SetAP(); }; class CWidgetAnnotation : public CAnnotation { diff --git a/PdfFile/SrcWriter/ResourcesDictionary.cpp b/PdfFile/SrcWriter/ResourcesDictionary.cpp index a4a9441364..eee1ba6b01 100644 --- a/PdfFile/SrcWriter/ResourcesDictionary.cpp +++ b/PdfFile/SrcWriter/ResourcesDictionary.cpp @@ -132,7 +132,7 @@ namespace PdfWriter return sKey; } - const char* CResourcesDict::GetXObjectName(CXObject* pObject) + const char* CResourcesDict::GetXObjectName(CObjectBase* pObject) { if (!m_pXObjects) { diff --git a/PdfFile/SrcWriter/ResourcesDictionary.h b/PdfFile/SrcWriter/ResourcesDictionary.h index 251789ee2d..47eb1d074d 100644 --- a/PdfFile/SrcWriter/ResourcesDictionary.h +++ b/PdfFile/SrcWriter/ResourcesDictionary.h @@ -48,7 +48,7 @@ namespace PdfWriter const char* GetFontName(CFontDict* pFont); const char* GetExtGrStateName(CExtGrState* pState); - const char* GetXObjectName(CXObject* pXObject); + const char* GetXObjectName(CObjectBase* pXObject); void AddXObjectWithName(const char* sXObjectName, CXObject* pXObject); void Fix(); diff --git a/PdfFile/SrcWriter/Types.h b/PdfFile/SrcWriter/Types.h index bfd04c1398..4a87cb6af3 100644 --- a/PdfFile/SrcWriter/Types.h +++ b/PdfFile/SrcWriter/Types.h @@ -89,6 +89,15 @@ namespace PdfWriter x = 0; y = 0; } + CMatrix(double d1, double d2, double d3, double d4, double d5, double d6) + { + m11 = d1; + m12 = d2; + m21 = d3; + m22 = d4; + x = d5; + y = d6; + } void Reset() { diff --git a/PdfFile/test/test.cpp b/PdfFile/test/test.cpp index 3249c9806c..6fce76d917 100644 --- a/PdfFile/test/test.cpp +++ b/PdfFile/test/test.cpp @@ -321,7 +321,7 @@ TEST_F(CPdfFileTest, SetMetaData) TEST_F(CPdfFileTest, ConvertToRaster) { - //GTEST_SKIP(); + GTEST_SKIP(); LoadFromFile(); @@ -372,7 +372,7 @@ TEST_F(CPdfFileTest, EditPdf) TEST_F(CPdfFileTest, EditPdfFromBase64) { - GTEST_SKIP(); + //GTEST_SKIP(); LoadFromFile(); ASSERT_TRUE(pdfFile->EditPdf(wsDstFile));