diff --git a/DesktopEditor/graphics/pro/js/drawingfile.json b/DesktopEditor/graphics/pro/js/drawingfile.json index f53041d321..05786c2286 100644 --- a/DesktopEditor/graphics/pro/js/drawingfile.json +++ b/DesktopEditor/graphics/pro/js/drawingfile.json @@ -29,6 +29,7 @@ "_GetGlyphs", "_GetLinks", "_GetStructure", + "_GetInteractiveForms", "_InitializeFontsBin", "_InitializeFontsBase64", "_InitializeFontsRanges", diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js index 9ff22d254a..dd1a6395ec 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js @@ -363,6 +363,41 @@ Module["_free"](ext); return res; }; + CFile.prototype["getInteractiveForms"] = function() + { + var res = []; + var ext = Module["_GetInteractiveForms"](this.nativeFile); + if (ext == 0) + return res; + + var lenArray = new Int32Array(Module["HEAP8"].buffer, ext, 4); + if (lenArray == null) + return res; + + var len = lenArray[0]; + len -= 4; + if (len <= 0) + return res; + + var buffer = new Uint8Array(Module["HEAP8"].buffer, ext + 4, len); + var reader = new CBinaryReader(buffer, 0, len); + + while (reader.isValid()) + { + var rec = {}; + rec["name"] = reader.readString(); + rec["page"] = reader.readInt(); + rec["x1"] = reader.readDouble(); + rec["y1"] = reader.readDouble(); + rec["x2"] = reader.readDouble(); + rec["y2"] = reader.readDouble(); + rec["type"] = reader.readString(); + res.push(rec); + } + + Module["_free"](ext); + return res; + }; CFile.prototype["getStructure"] = function() { var res = []; diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp index b61bf07a05..7df4fae4a4 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp @@ -150,6 +150,10 @@ WASM_EXPORT BYTE* GetStructure(CGraphicsFileDrawing* pGraphics) { return pGraphics->GetStructure(); } +WASM_EXPORT BYTE* GetInteractiveForms(CGraphicsFileDrawing* pGraphics) +{ + return pGraphics->GetInteractiveForms(); +} WASM_EXPORT void DestroyTextInfo(CGraphicsFileDrawing* pGraphics) { return pGraphics->DestroyText(); @@ -254,8 +258,8 @@ int main() nWidth = READ_INT(pInfo + nTestPage * 12 + 8); nHeight = READ_INT(pInfo + nTestPage * 12 + 12); int dpi = READ_INT(pInfo + nTestPage * 12 + 16); - nWidth *= (dpi / 25.4); - nHeight *= (dpi / 25.4); + //nWidth *= (dpi / 25.4); + //nHeight *= (dpi / 25.4); std::cout << "Page " << nTestPage << " width " << nWidth << " height " << nHeight << " dpi " << dpi << std::endl; nLength = READ_INT(pInfo + nPagesCount * 12 + 8); @@ -294,6 +298,7 @@ int main() RELEASEARRAYOBJECTS(res); } + // LINKS if (nPagesCount > 0) { BYTE* pLinks = GetLinks(pGrFile, nTestPage); @@ -329,6 +334,7 @@ int main() free(pLinks); } + // STRUCTURE if (true) { BYTE* pStructure = GetStructure(pGrFile); @@ -358,12 +364,53 @@ int main() free(pStructure); } + // GLYPHS if (false && nPagesCount > 0) { // TODO: BYTE* pGlyphs = GetGlyphs(pGrFile, nTestPage); } + // INTERACTIVE FORMS + if (true) + { + BYTE* pWidgets = GetInteractiveForms(pGrFile); + nLength = READ_INT(pWidgets); + DWORD i = 4; + nLength -= 4; + while (i < nLength) + { + DWORD nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "Name " << std::string((char*)(pWidgets + i), nPathLength) << ", "; + i += nPathLength; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "Page " << nPathLength << ", "; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "X1 " << (double)nPathLength / 100.0 << ", "; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "Y1 " << (double)nPathLength / 100.0 << ", "; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "X2 " << (double)nPathLength / 100.0 << ", "; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "Y2 " << (double)nPathLength / 100.0 << ", "; + nPathLength = READ_INT(pWidgets + i); + i += 4; + std::cout << "Type " << std::string((char*)(pWidgets + i), nPathLength) << std::endl; + i += nPathLength; + } + + std::cout << std::endl; + + if (pWidgets) + free(pWidgets); + } + Close(pGrFile); RELEASEARRAYOBJECTS(pCMapData); diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h index c5c7479cf1..baf838090c 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h @@ -110,6 +110,12 @@ public: { return pReader->GetStructure(); } + BYTE* GetInteractiveForms() + { + if (nType == 0) + return ((CPdfFile*)pReader)->GetWidgets(); + return NULL; + } std::wstring GetInfo() { return pReader->GetInfo(); @@ -125,7 +131,6 @@ public: if (nType == 0) ((CPdfFile*)pReader)->SetCMapMemory(pData, nSizeData); } - void DestroyText() { RELEASEOBJECT(pTextRenderer); diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index 59b193fada..5e19b7ecba 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -809,6 +809,12 @@ BYTE* CPdfFile::GetLinks(int nPageIndex) return NULL; return m_pInternal->pReader->GetLinks(nPageIndex); } +BYTE* CPdfFile::GetWidgets() +{ + if (!m_pInternal->pReader) + return NULL; + return m_pInternal->pReader->GetWidgets(); +} // ------------------------------------------------------------------------ diff --git a/PdfFile/PdfFile.h b/PdfFile/PdfFile.h index fa7faa6569..fec45689c2 100644 --- a/PdfFile/PdfFile.h +++ b/PdfFile/PdfFile.h @@ -102,6 +102,7 @@ public: // --- READER --- int GetError(); + bool IsNeedCMap(); void SetCMapMemory(BYTE* pData, DWORD nSizeData); void SetCMapFolder(const std::wstring& sFolder); @@ -119,9 +120,11 @@ public: virtual int GetPagesCount(); virtual void GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY); virtual void DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak); + virtual std::wstring GetInfo(); virtual BYTE* GetStructure(); virtual BYTE* GetLinks(int nPageIndex); + BYTE* GetWidgets(); // --- WRITER --- diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index ffb9cd2813..6dbcd3d292 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -49,6 +49,7 @@ #include "lib/xpdf/Outline.h" #include "lib/xpdf/Link.h" #include "lib/xpdf/TextOutputDev.h" +#include "lib/xpdf/AcroForm.h" #include "lib/goo/GList.h" #include @@ -715,7 +716,65 @@ BYTE* CPdfReader::GetLinks(int nPageIndex) return oLinks.Serialize(); } -BYTE* CPdfReader::GetWidget() +BYTE* CPdfReader::GetWidgets() { - return NULL; + if (!m_pPDFDocument || !m_pPDFDocument->getCatalog()) + return NULL; + + AcroForm* pAcroForms = m_pPDFDocument->getCatalog()->getForm(); + if (!pAcroForms) + return NULL; + + NSWasm::CData oRes; + oRes.SkipLen(); + + for (int i = 0, nNum = pAcroForms->getNumFields(); i < nNum; ++i) + { + AcroFormField* pField = pAcroForms->getField(i); + + // Полное имя поля + int nLengthName; + Unicode* uName = pField->getName(&nLengthName); + std::string sName = NSStringExt::CConverter::GetUtf8FromUTF32(uName, nLengthName); + oRes.WriteString((BYTE*)sName.c_str(), (unsigned int)sName.length()); + + // Номер страницы + int nPage = pField->getPageNum(); + oRes.AddInt(nPage - 1); + + // Координаты + double dx1, dy1, dx2, dy2; + pField->getBBox(&dx1, &dy1, &dx2, &dy2); + double height = m_pPDFDocument->getPageCropHeight(nPage); + oRes.AddDouble(dx1); + oRes.AddDouble(height - dy1); + oRes.AddDouble(dx2); + oRes.AddDouble(height - dy2); + + // Тип + AcroFormFieldType oType = pField->getAcroFormFieldType(); + std::string sType; + switch (oType) + { + case acroFormFieldPushbutton: sType = "pushbutton"; break; + case acroFormFieldRadioButton: sType = "radiobutton"; break; + case acroFormFieldCheckbox: sType = "checkbox"; break; + case acroFormFieldFileSelect: sType = "fileselect"; break; + case acroFormFieldMultilineText: sType = "multilinetext"; break; + case acroFormFieldText: sType = "text"; break; + case acroFormFieldBarcode: sType = "barcode"; break; + case acroFormFieldComboBox: sType = "combobox"; break; + case acroFormFieldListBox: sType = "listbox"; break; + case acroFormFieldSignature: sType = "signature"; break; + default: sType = ""; break; + } + oRes.WriteString((BYTE*)sType.c_str(), (unsigned int)sType.length()); + + // TO DO здесь возможно записать флаги необходимые каждому типу + } + + oRes.WriteLen(); + BYTE* bRes = oRes.GetBuffer(); + oRes.ClearWithoutAttack(); + return bRes; } diff --git a/PdfFile/PdfReader.h b/PdfFile/PdfReader.h index 21e6e22198..022e5de94b 100644 --- a/PdfFile/PdfReader.h +++ b/PdfFile/PdfReader.h @@ -69,7 +69,7 @@ public: BYTE* GetStructure(); BYTE* GetLinks(int nPageIndex); - BYTE* GetWidget(); + BYTE* GetWidgets(); private: PDFDoc* m_pPDFDocument;