From 9871f3c0f18f618ee6df0b656bd8422bc9090939 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 20 Oct 2023 14:33:25 +0300 Subject: [PATCH] Release getButtonIcons with base64 image --- .../pro/js/wasm/js/drawingfile_base.js | 27 ++++-- .../graphics/pro/js/wasm/src/drawingfile.cpp | 4 +- .../graphics/pro/js/wasm/src/drawingfile.h | 26 +++--- .../pro/js/wasm/src/drawingfile_test.cpp | 58 ++++++++---- PdfFile/PdfFile.cpp | 92 +++++++++++-------- PdfFile/PdfFile.h | 6 +- PdfFile/PdfReader.cpp | 59 ++++++++++-- PdfFile/PdfReader.h | 8 +- PdfFile/SrcWriter/Annotation.cpp | 1 + 9 files changed, 188 insertions(+), 93 deletions(-) diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js index 47776634fd..445fa9a718 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js @@ -790,9 +790,9 @@ } if (flags & (1 << 14)) { - rec["NameOfYes"] = reader.readString(); + rec["ExportValue"] = reader.readString(); if (flags & (1 << 9)) - rec["value"] = rec["NameOfYes"]; + rec["value"] = rec["ExportValue"]; } // 12.7.4.2.1 rec["NoToggleToOff"] = (rec["flag"] >> 14) & 1; // NoToggleToOff @@ -854,7 +854,7 @@ }; // optional nWidget - rec["AP"]["i"] // optional sView - N/D/R - // optional sButtonView - state pushbutton-annotation - Off/Yes(or rec["NameOfYes"]) + // optional sButtonView - state pushbutton-annotation - Off/Yes(or rec["ExportValue"]) CFile.prototype["getInteractiveFormsAP"] = function(pageIndex, width, height, backgroundColor, nWidget, sView, sButtonView) { let nView = -1; @@ -899,9 +899,10 @@ Module["_free"](ext); return res; }; + // optional bBase64 - true/false base64 result // optional nWidget ... // optional sIconView - icon - I/RI/IX - CFile.prototype["getButtonIcons"] = function(pageIndex, width, height, backgroundColor, nWidget, sIconView) + CFile.prototype["getButtonIcons"] = function(pageIndex, width, height, backgroundColor, nWidget, bBase64, sIconView) { let nView = -1; if (sIconView) @@ -915,7 +916,7 @@ } let res = {}; - let ext = Module["_GetButtonIcons"](this.nativeFile, width, height, backgroundColor === undefined ? 0xFFFFFF : backgroundColor, pageIndex, nWidget === undefined ? -1 : nWidget, nView); + let ext = Module["_GetButtonIcons"](this.nativeFile, width, height, backgroundColor === undefined ? 0xFFFFFF : backgroundColor, pageIndex, nWidget === undefined ? -1 : nWidget, bBase64 === undefined ? false : bBase64, nView); if (ext == 0) return res; @@ -952,10 +953,18 @@ ViewMK["j"] = MK[MKType]; ViewMK["w"] = reader.readInt(); ViewMK["h"] = reader.readInt(); - let np1 = reader.readInt(); - let np2 = reader.readInt(); - // this memory needs to be deleted - ViewMK["retValue"] = np2 << 32 | np1; + if (bBase64) + { + // base64 string with image + ViewMK["retValue"] = reader.readString(); + } + else + { + let np1 = reader.readInt(); + let np2 = reader.readInt(); + // this memory needs to be deleted + ViewMK["retValue"] = np2 << 32 | np1; + } res["View"].push(ViewMK); } } diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp index 50b093a15a..d6fbcf04b1 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp @@ -174,7 +174,7 @@ WASM_EXPORT BYTE* GetInteractiveFormsAP(CGraphicsFileDrawing* pGraphics, int nRa return pGraphics->GetAPWidget(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nWidget, sView, sButtonView); } -WASM_EXPORT BYTE* GetButtonIcons(CGraphicsFileDrawing* pGraphics, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nButtonWidget, int nIconView) +WASM_EXPORT BYTE* GetButtonIcons(CGraphicsFileDrawing* pGraphics, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, bool bBase64, int nButtonWidget, int nIconView) { const char* sIconView = NULL; if (nIconView == 0) @@ -184,7 +184,7 @@ WASM_EXPORT BYTE* GetButtonIcons(CGraphicsFileDrawing* pGraphics, int nRasterW, else if (nIconView == 2) sIconView = "IX"; - return pGraphics->GetButtonIcon(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nButtonWidget, sIconView); + return pGraphics->GetButtonIcon(nRasterW, nRasterH, nBackgroundColor, nPageIndex, bBase64, nButtonWidget, sIconView); } WASM_EXPORT BYTE* GetAnnotationsInfo(CGraphicsFileDrawing* pGraphics, int nPageIndex) { diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h index 332b7cbf3b..7d2dccf469 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h @@ -123,25 +123,25 @@ public: return ((CPdfFile*)pReader)->GetWidgets(); return NULL; } - BYTE* GetAPWidget(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sButtonView = NULL) - { - if (nType == 0) - return ((CPdfFile*)pReader)->GetAPWidget(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nWidget, sView, sButtonView); - return NULL; - } - BYTE* GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nButtonWidget = -1, const char* sIconView = NULL) - { - if (nType == 0) - return ((CPdfFile*)pReader)->GetButtonIcon(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nButtonWidget, sIconView); - return NULL; - } BYTE* GetAnnots(int nPageIndex = -1) { if (nType == 0) return ((CPdfFile*)pReader)->GetAnnots(nPageIndex); return NULL; } - BYTE* GetAPAnnots(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL) + BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL) + { + if (nType == 0) + return ((CPdfFile*)pReader)->GetAPWidget(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nWidget, sView, sBView); + return NULL; + } + BYTE* GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, bool bBase64, int nBWidget = -1, const char* sIView = NULL) + { + if (nType == 0) + return ((CPdfFile*)pReader)->GetButtonIcon(nRasterW, nRasterH, nBackgroundColor, nPageIndex, bBase64, nBWidget, sIView); + return NULL; + } + BYTE* GetAPAnnots (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL) { if (nType == 0) return ((CPdfFile*)pReader)->GetAPAnnots(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nAnnot, sView); diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index 4631e31616..566e3a0faf 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -915,7 +915,8 @@ int main(int argc, char* argv[]) if (pWidgetsAP) free(pWidgetsAP); - BYTE* pWidgetsMK = GetButtonIcons(pGrFile, nWidth, nHeight, 0xFFFFFF, nTestPage, -1, -1); + bool bBase64 = true; + BYTE* pWidgetsMK = GetButtonIcons(pGrFile, nWidth, nHeight, 0xFFFFFF, nTestPage, bBase64, -1, -1); nLength = READ_INT(pWidgetsMK); i = 4; nLength -= 4; @@ -950,21 +951,46 @@ int main(int argc, char* argv[]) int nWidgetHeight = READ_INT(pWidgetsMK + i); i += 4; std::cout << "H " << nWidgetHeight << ", "; - unsigned long long npBgraData1 = READ_INT(pWidgetsMK + i); - i += 4; - unsigned long long npBgraData2 = READ_INT(pWidgetsMK + i); - i += 4; - BYTE* res = (BYTE*)(npBgraData2 << 32 | npBgraData1); - CBgraFrame oFrame; - oFrame.put_Data(res); - oFrame.put_Width(nWidgetWidth); - oFrame.put_Height(nWidgetHeight); - oFrame.put_Stride(4 * nWidgetWidth); - oFrame.put_IsRGBA(true); - oFrame.SaveFile(NSFile::GetProcessDirectory() + L"/res_" + std::to_wstring(nAP) + L"_MK_" + UTF8_TO_U(sMKName) + L".png", _CXIMAGE_FORMAT_PNG); - oFrame.ClearNoAttack(); - RELEASEARRAYOBJECTS(res); + if (bBase64) + { + nPathLength = READ_INT(pWidgetsMK + i); + i += 4; + BYTE* pBase64 = pWidgetsMK + i; + i += nPathLength; + + int nLenDst = NSBase64::Base64DecodeGetRequiredLength(nPathLength); + BYTE* pDataDst = new BYTE[nLenDst]; + + if (NSBase64::Base64Decode((const char*)pBase64, nPathLength, pDataDst, &nLenDst)) + { + NSFile::CFileBinary oFile; + if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/res_" + std::to_wstring(nAP) + L"_MK_" + UTF8_TO_U(sMKName) + L".png")) + { + oFile.WriteFile(pDataDst, nLenDst); + oFile.CloseFile(); + } + } + RELEASEARRAYOBJECTS(pDataDst); + } + else + { + unsigned long long npBgraData1 = READ_INT(pWidgetsMK + i); + i += 4; + unsigned long long npBgraData2 = READ_INT(pWidgetsMK + i); + i += 4; + + BYTE* res = (BYTE*)(npBgraData2 << 32 | npBgraData1); + CBgraFrame oFrame; + oFrame.put_Data(res); + oFrame.put_Width(nWidgetWidth); + oFrame.put_Height(nWidgetHeight); + oFrame.put_Stride(4 * nWidgetWidth); + oFrame.put_IsRGBA(true); + oFrame.SaveFile(NSFile::GetProcessDirectory() + L"/res_" + std::to_wstring(nAP) + L"_MK_" + UTF8_TO_U(sMKName) + L".png", _CXIMAGE_FORMAT_PNG); + oFrame.ClearNoAttack(); + RELEASEARRAYOBJECTS(res); + } } std::cout << std::endl; } @@ -992,7 +1018,7 @@ int main(int argc, char* argv[]) ReadAnnot(pAnnots, i); - // Markup + // Markup DWORD nFlags = 0; if ((nPathLength < 18 && nPathLength != 1 && nPathLength != 15) || nPathLength == 25) diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index 7525e09441..39fffbf282 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -399,6 +399,45 @@ void CPdfFile::RotatePage(int nRotate) m_pInternal->pWriter->PageRotate(nRotate); } #ifndef BUILDING_WASM_MODULE +PdfWriter::CDictObject* GetAcroForm(Object* oAcroForm) +{ + if (!oAcroForm || !oAcroForm->isDict()) + return NULL; + + PdfWriter::CDictObject* pAcroForm = new PdfWriter::CDictObject(); + + for (int nIndex = 0; nIndex < oAcroForm->dictGetLength(); ++nIndex) + { + Object oTemp2; + char* chKey = oAcroForm->dictGetKey(nIndex); + if (strcmp("DR", chKey) == 0) + { + oAcroForm->dictGetVal(nIndex, &oTemp2); + if (!oTemp2.isDict()) + { + oTemp2.free(); + continue; + } + + PdfWriter::CResourcesDict* pDR = new PdfWriter::CResourcesDict(NULL, true, false); + pAcroForm->Add(chKey, pDR); + for (int nIndex = 0; nIndex < oTemp2.dictGetLength(); ++nIndex) + { + + } + oTemp2.free(); + continue; + } + oAcroForm->dictGetValNF(nIndex, &oTemp2); + DictToCDictObject(&oTemp2, pAcroForm, false, chKey); + oTemp2.free(); + } + + if (!pAcroForm->Get("Fields")) + pAcroForm->Add("Fields", new PdfWriter::CArrayObject()); + + return pAcroForm; +} bool CPdfFile::EditPdf(const std::wstring& wsDstFile) { if (wsDstFile.empty()) @@ -486,39 +525,12 @@ bool CPdfFile::EditPdf(const std::wstring& wsDstFile) if (strcmp("AcroForm", chKey) == 0) { catDict.dictGetVal(nIndex, &oTemp); - if (!oTemp.isDict()) - continue; - - PdfWriter::CDictObject* pAcroForm = new PdfWriter::CDictObject(); - pCatalog->Add(chKey, pAcroForm); - for (int nIndex = 0; nIndex < oTemp.dictGetLength(); ++nIndex) - { - Object oTemp2; - char* chKey = oTemp.dictGetKey(nIndex); - if (strcmp("DR", chKey) == 0) - { - oTemp.dictGetVal(nIndex, &oTemp2); - if (!oTemp2.isDict()) - continue; - - PdfWriter::CResourcesDict* pDR = new PdfWriter::CResourcesDict(NULL, true, false); - pAcroForm->Add(chKey, pDR); - for (int nIndex = 0; nIndex < oTemp2.dictGetLength(); ++nIndex) - { - - } - oTemp2.free(); - continue; - } - oTemp.dictGetValNF(nIndex, &oTemp2); - DictToCDictObject(&oTemp2, pAcroForm, false, chKey); - oTemp2.free(); - } + PdfWriter::CDictObject* pAcroForm = GetAcroForm(&oTemp); oTemp.free(); - - if (!pAcroForm->Get("Fields")) - pAcroForm->Add("Fields", new PdfWriter::CArrayObject()); - + if (pAcroForm) + { + pCatalog->Add(chKey, pAcroForm); + } continue; } else @@ -1190,6 +1202,12 @@ BYTE* CPdfFile::GetWidgets() return NULL; return m_pInternal->pReader->GetWidgets(); } +BYTE* CPdfFile::GetAnnots(int nPageIndex) +{ + if (!m_pInternal->pReader) + return NULL; + return m_pInternal->pReader->GetAnnots(nPageIndex); +} BYTE* CPdfFile::VerifySign(const std::wstring& sFile, ICertificate* pCertificate, int nWidget) { if (!m_pInternal->pReader) @@ -1202,17 +1220,11 @@ BYTE* CPdfFile::GetAPWidget(int nRasterW, int nRasterH, int nBackgroundColor, in return NULL; return m_pInternal->pReader->GetAPWidget(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nWidget, sView, sButtonView); } -BYTE* CPdfFile::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nButtonWidget, const char* sIconView) +BYTE* CPdfFile::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, bool bBase64, int nButtonWidget, const char* sIconView) { if (!m_pInternal->pReader) return NULL; - return m_pInternal->pReader->GetButtonIcon(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nButtonWidget, sIconView); -} -BYTE* CPdfFile::GetAnnots(int nPageIndex) -{ - if (!m_pInternal->pReader) - return NULL; - return m_pInternal->pReader->GetAnnots(nPageIndex); + return m_pInternal->pReader->GetButtonIcon(nRasterW, nRasterH, nBackgroundColor, nPageIndex, bBase64, nButtonWidget, sIconView); } BYTE* CPdfFile::GetAPAnnots(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot, const char* sView) { diff --git a/PdfFile/PdfFile.h b/PdfFile/PdfFile.h index 0c2a6d667c..7730f667aa 100644 --- a/PdfFile/PdfFile.h +++ b/PdfFile/PdfFile.h @@ -130,9 +130,9 @@ public: BYTE* GetWidgets(); BYTE* GetAnnots (int nPageIndex = -1); BYTE* VerifySign (const std::wstring& sFile, ICertificate* pCertificate, int nWidget = -1); - BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sButtonView = NULL); - BYTE* GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nButtonWidget = -1, const char* sIconView = NULL); - BYTE* GetAPAnnots (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL); + BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL); + BYTE* GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, bool bBase64 = false, int nBWidget = -1, const char* sIView = NULL); + BYTE* GetAPAnnots (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL); // --- WRITER --- diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 2202ad5e56..bc51117068 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -909,7 +909,7 @@ BYTE* CPdfReader::GetAPWidget(int nRasterW, int nRasterH, int nBackgroundColor, oRes.ClearWithoutAttack(); return bRes; } -BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nButtonWidget, const char* sIconView) +BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, bool bBase64, int nButtonWidget, const char* sIconView) { if (!m_pPDFDocument || !m_pPDFDocument->getCatalog()) return NULL; @@ -1018,6 +1018,34 @@ BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor oRes.AddInt(nHeight); oWidth.free(); oHeight.free(); + if (bBase64) + { + int nLength = 0; + Object oLength; + if (oImDict->lookup("Length", &oLength)->isInt()) + nLength = oLength.getInt(); + oLength.free(); + + // TODO используется размер закодированного потока, а необходим размер после декодирования, и DecodeLength есть не всегда + BYTE* pBuffer = new BYTE[nLength]; + BYTE* pBufferPtr = pBuffer; + + Stream* pImage = oIm.getStream()->getUndecodedStream(); + for (int nI = 0; nI < nLength; ++nI) + *pBufferPtr++ = (BYTE)pImage->getChar(); + + char* cData64 = NULL; + int nData64Dst = 0; + NSFile::CBase64Converter::Encode(pBuffer, nLength, cData64, nData64Dst); + + oRes.WriteString((BYTE*)cData64, nData64Dst); + + nMKLength++; + RELEASEARRAYOBJECTS(pBuffer); + RELEASEARRAYOBJECTS(cData64); + continue; + } + BYTE* pBgraData = new BYTE[nWidth * nHeight * 4]; unsigned int nColor = (unsigned int)nBackgroundColor; unsigned int nSize = (unsigned int)(nWidth * nHeight); @@ -1239,13 +1267,32 @@ BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor oStr.free(); oStrRef.free(); oResources.free(); nMKLength++; - unsigned long long npSubMatrix = (unsigned long long)pBgraData; - unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; - oRes.AddInt(npSubMatrix1); - oRes.AddInt(npSubMatrix >> 32); + + if (bBase64) + { + BYTE* pPngBuffer = NULL; + int nPngSize = 0; + pFrame->Encode(pPngBuffer, nPngSize, 4); + + char* cData64 = NULL; + int nData64Dst = 0; + NSFile::CBase64Converter::Encode(pPngBuffer, nPngSize, cData64, nData64Dst); + + oRes.WriteString((BYTE*)cData64, nData64Dst); + + RELEASEARRAYOBJECTS(cData64); + } + else + { + unsigned long long npSubMatrix = (unsigned long long)pBgraData; + unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; + oRes.AddInt(npSubMatrix1); + oRes.AddInt(npSubMatrix >> 32); + + pFrame->ClearNoAttack(); + } delete gfx; - pFrame->ClearNoAttack(); RELEASEOBJECT(pFrame); RELEASEOBJECT(pRenderer); } diff --git a/PdfFile/PdfReader.h b/PdfFile/PdfReader.h index 642bccd0f3..f22ed34098 100644 --- a/PdfFile/PdfReader.h +++ b/PdfFile/PdfReader.h @@ -74,11 +74,11 @@ public: BYTE* GetStructure(); BYTE* GetLinks(int nPageIndex); BYTE* GetWidgets(); - BYTE* VerifySign(const std::wstring& sFile, ICertificate* pCertificate, int nWidget = -1); - BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sButtonView = NULL); - BYTE* GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nButtonWidget = -1, const char* sIconView = NULL); BYTE* GetAnnots(int nPageIndex = -1); - BYTE* GetAPAnnots(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL); + BYTE* VerifySign(const std::wstring& sFile, ICertificate* pCertificate, int nWidget = -1); + BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL); + BYTE* GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, bool bBase64 = false, int nBWidget = -1, const char* sIView = NULL); + BYTE* GetAPAnnots (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nAnnot = -1, const char* sView = NULL); private: IOfficeDrawingFile* m_pRenderer; diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index c378d02ffc..7191c29eff 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -1207,6 +1207,7 @@ namespace PdfWriter if (pDA) m_pStream->WriteStr((const char*)pDA->GetString()); + // TODO возможно потребуется смещение Y-координаты в зависимости от размеров области и размеров шрифта m_pStream->WriteStr(" 2 6.548 Td ("); m_pStream->WriteStr(pAnnot->GetV().c_str()); m_pStream->WriteStr(") Tj ET Q");