From d4de820fa3d01a0943bc82bbe273a8410cd28dde Mon Sep 17 00:00:00 2001 From: Kulikova Svetlana Date: Thu, 5 Aug 2021 14:30:22 +0300 Subject: [PATCH] xps external and internal links --- .../graphics/pro/js/wasm/src/wasmgraphics.cpp | 76 +++++++++++- .../graphics/pro/js/wasm/src/wasmgraphics.h | 8 ++ XpsFile/XpsFile.cpp | 8 ++ XpsFile/XpsFile.h | 2 + XpsFile/XpsLib/Document.cpp | 16 +++ XpsFile/XpsLib/Document.h | 3 + XpsFile/XpsLib/Page.cpp | 116 +++++++++++++++++- XpsFile/XpsLib/Page.h | 7 +- 8 files changed, 228 insertions(+), 8 deletions(-) diff --git a/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.cpp b/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.cpp index 0e019c44d9..6b6a0d68d2 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.cpp @@ -36,12 +36,12 @@ WASM_EXPORT CGraphicsFileDrawing* DJVU_Load(BYTE* data, LONG size) pGraphics->LoadFromMemory(data, size); return pGraphics; } -WASM_EXPORT void XPS_Close (CGraphicsFileDrawing* pGraphics) +WASM_EXPORT void XPS_Close (CGraphicsFileDrawing* pGraphics) { delete pGraphics; RELEASEOBJECT(CApplicationFontStreams::m_pMemoryStorage); } -WASM_EXPORT int* XPS_GetInfo (CGraphicsFileDrawing* pGraphics) +WASM_EXPORT int* XPS_GetInfo (CGraphicsFileDrawing* pGraphics) { int pages_count = pGraphics->GetPagesCount(); int* buffer = new int[pages_count * 3 + 1]; @@ -59,11 +59,11 @@ WASM_EXPORT int* XPS_GetInfo (CGraphicsFileDrawing* pGraphics) } return buffer; } -WASM_EXPORT BYTE* XPS_GetPixmap(CGraphicsFileDrawing* pGraphics, int nPageIndex, int nRasterW, int nRasterH) +WASM_EXPORT BYTE* XPS_GetPixmap (CGraphicsFileDrawing* pGraphics, int nPageIndex, int nRasterW, int nRasterH) { return pGraphics->GetPage(nPageIndex, nRasterW, nRasterH); } -WASM_EXPORT BYTE* XPS_GetGlyphs(CGraphicsFileDrawing* pGraphics, int nPageIndex, int nRasterW, int nRasterH) +WASM_EXPORT BYTE* XPS_GetGlyphs (CGraphicsFileDrawing* pGraphics, int nPageIndex, int nRasterW, int nRasterH) { return pGraphics->GetXPSGlyphs(nPageIndex, nRasterW, nRasterH); } @@ -71,6 +71,14 @@ WASM_EXPORT BYTE* DJVU_GetGlyphs(CGraphicsFileDrawing* pGraphics, int nPageIndex { return pGraphics->GetDJVUGlyphs(nPageIndex, nRasterW, nRasterH); } +WASM_EXPORT BYTE* XPS_GetExternalLinks(CGraphicsFileDrawing* pGraphics, int nPageIndex) +{ + return pGraphics->GetXPSExternalLinks(nPageIndex); +} +WASM_EXPORT BYTE* XPS_GetInternalLinks(CGraphicsFileDrawing* pGraphics, int nPageIndex) +{ + return pGraphics->GetXPSInternalLinks(nPageIndex); +} WASM_EXPORT BYTE* XPS_GetStructure(CGraphicsFileDrawing* pGraphics) { return pGraphics->GetXPSStructure(); @@ -116,7 +124,7 @@ int main() int width = info[1] * 96 / info[3]; int height = info[2] * 96 / info[3]; - BYTE* pGlyphs = XPS_GetGlyphs(test, 0, width, height); + BYTE* pGlyphs = XPS_GetGlyphs(test, 22, width, height); DWORD nLength = GetLength(pGlyphs); DWORD i = 4; nLength -= 4; @@ -152,10 +160,11 @@ int main() BYTE* res = NULL; if (pages_count > 0) - res = XPS_GetPixmap(test, 0, width, height); + res = XPS_GetPixmap(test, 22, width, height); for (int i = 0; i < 100; i++) std::cout << (int)res[i] << " "; + std::cout << std::endl; CBgraFrame* resFrame = new CBgraFrame(); resFrame->put_Data(res); @@ -166,6 +175,61 @@ int main() resFrame->SaveFile(NSFile::GetProcessDirectory() + L"/res.png", _CXIMAGE_FORMAT_PNG); resFrame->ClearNoAttack(); + BYTE* pInternal = XPS_GetInternalLinks(test, 22); + nLength = GetLength(pInternal); + i = 4; + nLength -= 4; + while (i < nLength) + { + DWORD nPathLength = GetLength(pInternal + i); + i += 4; + std::cout << "Page "<< nPathLength; + nPathLength = GetLength(pInternal + i); + i += 4; + std::cout << " X "<< std::string((char*)(pInternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pInternal + i); + i += 4; + std::cout << " Y "<< std::string((char*)(pInternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pInternal + i); + i += 4; + std::cout << " W "<< std::string((char*)(pInternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pInternal + i); + i += 4; + std::cout << " H "<< std::string((char*)(pInternal + i), nPathLength) << std::endl; + i += nPathLength; + } + + BYTE* pExternal = XPS_GetExternalLinks(test, 22); + nLength = GetLength(pExternal); + i = 4; + nLength -= 4; + while (i < nLength) + { + DWORD nPathLength = GetLength(pExternal + i); + i += 4; + std::cout << "X "<< std::string((char*)(pExternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pExternal + i); + i += 4; + std::cout << " Y "<< std::string((char*)(pExternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pExternal + i); + i += 4; + std::cout << " W "<< std::string((char*)(pExternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pExternal + i); + i += 4; + std::cout << " H "<< std::string((char*)(pExternal + i), nPathLength); + i += nPathLength; + nPathLength = GetLength(pExternal + i); + i += 4; + std::cout << " Link "<< std::string((char*)(pExternal + i), nPathLength) << std::endl; + i += nPathLength; + } + BYTE* pStructure = XPS_GetStructure(test); nLength = GetLength(pStructure); i = 4; diff --git a/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.h b/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.h index 71dc0d0760..33f5361577 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.h +++ b/DesktopEditor/graphics/pro/js/wasm/src/wasmgraphics.h @@ -82,6 +82,14 @@ public: { return ((CDjVuFile*)pReader)->GetPageGlyphs(nPageIndex, nRasterW, nRasterH); } + BYTE* GetXPSExternalLinks(int nPageIndex) + { + return ((CXpsFile*)pReader)->GetExternalLinks(nPageIndex); + } + BYTE* GetXPSInternalLinks(int nPageIndex) + { + return ((CXpsFile*)pReader)->GetInternalLinks(nPageIndex); + } BYTE* GetXPSStructure() { return ((CXpsFile*)pReader)->GetStructure(); diff --git a/XpsFile/XpsFile.cpp b/XpsFile/XpsFile.cpp index e552db4a27..ab3b609b89 100644 --- a/XpsFile/XpsFile.cpp +++ b/XpsFile/XpsFile.cpp @@ -293,4 +293,12 @@ BYTE* CXpsFile::GetStructure() { return m_pInternal->m_pDocument->GetStructure(); } +BYTE* CXpsFile::GetExternalLinks(int nPageIndex) +{ + return m_pInternal->m_pDocument->GetExternalLinks(nPageIndex); +} +BYTE* CXpsFile::GetInternalLinks(int nPageIndex) +{ + return m_pInternal->m_pDocument->GetInternalLinks(nPageIndex); +} #endif diff --git a/XpsFile/XpsFile.h b/XpsFile/XpsFile.h index 1ede40300a..e6063b209c 100644 --- a/XpsFile/XpsFile.h +++ b/XpsFile/XpsFile.h @@ -69,6 +69,8 @@ public: #ifdef BUILDING_WASM_MODULE BYTE* GetGlyphs(int nPageIndex, int nRasterW, int nRasterH); BYTE* GetStructure(); + BYTE* GetExternalLinks(int nPageIndex); + BYTE* GetInternalLinks(int nPageIndex); #endif private: diff --git a/XpsFile/XpsLib/Document.cpp b/XpsFile/XpsLib/Document.cpp index 5faecb289a..276bf0186a 100644 --- a/XpsFile/XpsLib/Document.cpp +++ b/XpsFile/XpsLib/Document.cpp @@ -257,6 +257,8 @@ namespace XPS std::vector::iterator find = std::find_if(m_vStructure.begin(), m_vStructure.end(), [wsNameTarget](const CDocumentStructure& str){ return str.wsTarget == wsNameTarget; }); if (find != m_vStructure.end()) find->nPage = nIndex; + else + m_mInternalLinks.insert(std::pair(wsNameTarget, nIndex)); } } } @@ -306,6 +308,20 @@ namespace XPS return oIter->second->GetGlyphs(); return NULL; } + BYTE* CDocument::GetExternalLinks(int nPageIndex) + { + std::map::const_iterator oIter = m_mPages.find(nPageIndex); + if (oIter != m_mPages.end()) + return oIter->second->GetExternalLinks(); + return NULL; + } + BYTE* CDocument::GetInternalLinks(int nPageIndex) + { + std::map::const_iterator oIter = m_mPages.find(nPageIndex); + if (oIter != m_mPages.end()) + return oIter->second->GetInternalLinks(); + return NULL; + } #endif void CDocument::DrawPage(int nPageIndex, IRenderer* pRenderer, bool* pbBreak) { diff --git a/XpsFile/XpsLib/Document.h b/XpsFile/XpsLib/Document.h index 606a303a2a..72344511ce 100644 --- a/XpsFile/XpsLib/Document.h +++ b/XpsFile/XpsLib/Document.h @@ -69,7 +69,10 @@ namespace XPS }; BYTE* GetStructure(); BYTE* GetPageGlyphs(int nPageIndex); + BYTE* GetExternalLinks(int nPageIndex); + BYTE* GetInternalLinks(int nPageIndex); std::vector m_vStructure; + std::map m_mInternalLinks; #endif private: diff --git a/XpsFile/XpsLib/Page.cpp b/XpsFile/XpsLib/Page.cpp index 32853ee8a6..de5ebbd5f1 100644 --- a/XpsFile/XpsLib/Page.cpp +++ b/XpsFile/XpsLib/Page.cpp @@ -187,6 +187,51 @@ namespace XPS } return NULL; } + BYTE* Page::GetExternalLinks() + { + CData oRes; + oRes.SkipLen(); + for (const CPageLink& link : m_vExternalLinks) + { + std::string s = std::to_string(link.dX); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = std::to_string(link.dY); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = std::to_string(link.dW); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = std::to_string(link.dH); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = U_TO_UTF8(link.sLink); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + } + oRes.WriteLen(); + + BYTE* res = oRes.GetBuffer(); + oRes.ClearWithoutAttack(); + return res; + } + BYTE* Page::GetInternalLinks() + { + CData oRes; + oRes.SkipLen(); + for (const CPageLink& link : m_vInternalLinks) + { + oRes.AddInt(link.nPage); + std::string s = std::to_string(link.dX); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = std::to_string(link.dY); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = std::to_string(link.dW); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + s = std::to_string(link.dH); + oRes.WriteString((BYTE*)s.c_str(), s.length()); + } + oRes.WriteLen(); + + BYTE* res = oRes.GetBuffer(); + oRes.ClearWithoutAttack(); + return res; + } #endif void Page::Draw(IRenderer* pRenderer, bool* pbBreak) { @@ -972,12 +1017,81 @@ namespace XPS } else if (L"FixedPage.NavigateUri" == wsAttrName) { + CPageLink oLink = {0,0,0,0,L"",-1}; std::wstring wsPath = wsPathData.c_stdstr(); + size_t nFindX = wsPath.find(L"M "); + if (nFindX != std::wstring::npos) + { + nFindX += 2; + size_t nFindEndX = wsPath.find(L',', nFindX); + if (nFindEndX != std::wstring::npos) + { + oLink.dX = GetDouble(wsPath.substr(nFindX, nFindEndX - nFindX)); + size_t nFindY = nFindEndX + 1; + size_t nFindEndY = wsPath.find(L' ', nFindY); + if (nFindEndY != std::wstring::npos) + oLink.dY = GetDouble(wsPath.substr(nFindY, nFindEndY - nFindY)); + } + } + double MaybeH = 0; + double MaybeW = 0; + nFindX = wsPath.find(L"L "); + if (nFindX != std::wstring::npos) + { + nFindX += 2; + size_t nFindEndX = wsPath.find(L',', nFindX); + if (nFindEndX != std::wstring::npos) + { + MaybeW = GetDouble(wsPath.substr(nFindX, nFindEndX - nFindX)); + size_t nFindY = nFindEndX + 1; + size_t nFindEndY = wsPath.find(L' ', nFindY); + if (nFindEndY != std::wstring::npos) + MaybeH = GetDouble(wsPath.substr(nFindY, nFindEndY - nFindY)); + if (MaybeW == oLink.dX) + oLink.dH = MaybeH - oLink.dY; + if (MaybeH == oLink.dY) + oLink.dW = MaybeW - oLink.dX; + } + } + nFindX = wsPath.find(L"L ", nFindX); + if (nFindX != std::wstring::npos) + { + nFindX += 2; + size_t nFindEndX = wsPath.find(L',', nFindX); + if (nFindEndX != std::wstring::npos) + { + double MaybeInH = 0; + double MaybeInW = GetDouble(wsPath.substr(nFindX, nFindEndX - nFindX)); + size_t nFindY = nFindEndX + 1; + size_t nFindEndY = wsPath.find(L' ', nFindY); + if (nFindEndY != std::wstring::npos) + MaybeInH = GetDouble(wsPath.substr(nFindY, nFindEndY - nFindY)); + if (MaybeInW == MaybeW) + oLink.dH = MaybeInH - oLink.dY; + if (MaybeInH == MaybeH) + oLink.dW = MaybeInW - oLink.dX; + } + } std::wstring wsNameTarget = oReader.GetText(); if (wsNameTarget.find(L"http") == 0) { - m_vExternalLinks.push_back({}); + oLink.sLink = wsNameTarget; + m_vExternalLinks.push_back(oLink); + } + else + { + size_t nSharp = wsNameTarget.find(L'#'); + if (nSharp != std::wstring::npos) + { + oLink.sLink = wsNameTarget.substr(nSharp + 1); + std::map::iterator find = m_pDocument->m_mInternalLinks.find(oLink.sLink); + if (find != m_pDocument->m_mInternalLinks.end()) + { + oLink.nPage = find->second; + m_vInternalLinks.push_back(oLink); + } + } } } #endif diff --git a/XpsFile/XpsLib/Page.h b/XpsFile/XpsLib/Page.h index e15e079123..d1d2afe532 100644 --- a/XpsFile/XpsLib/Page.h +++ b/XpsFile/XpsLib/Page.h @@ -55,6 +55,8 @@ namespace XPS void GetSize(int& nW, int& nH) const; #ifdef BUILDING_WASM_MODULE BYTE* GetGlyphs(); + BYTE* GetExternalLinks(); + BYTE* GetInternalLinks(); class CData { protected: @@ -178,14 +180,17 @@ namespace XPS } }; CData* m_pGlyphs; - class CPageLink + struct CPageLink { double dX; double dY; double dW; double dH; + std::wstring sLink; + int nPage; }; std::vector m_vExternalLinks; + std::vector m_vInternalLinks; #endif void Draw(IRenderer* pRenderer, bool* pbBreak);