Fix CPdfReader functions

This commit is contained in:
Svetlana Kulikova
2025-02-25 17:48:42 +03:00
parent f28dc0a36a
commit 4085f58b09
2 changed files with 161 additions and 101 deletions

View File

@ -410,41 +410,38 @@ bool CPdfReader::LoadFromFile(NSFonts::IApplicationFonts* pAppFonts, const std::
return true; return true;
} }
bool CPdfReader::LoadFromMemory(NSFonts::IApplicationFonts* pAppFonts, BYTE* data, DWORD length, const std::wstring& owner_password, const std::wstring& user_password) bool CPdfReader::LoadFromMemory(NSFonts::IApplicationFonts* pAppFonts, BYTE* data, DWORD length, const std::wstring& wsOwnerPassword, const std::wstring& wsUserPassword)
{ {
Clear();
RELEASEINTERFACE(m_pFontManager); RELEASEINTERFACE(m_pFontManager);
m_pFontManager = pAppFonts->GenerateFontManager(); m_pFontManager = InitFontManager(pAppFonts);
NSFonts::IFontsCache* pMeasurerCache = NSFonts::NSFontCache::Create();
pMeasurerCache->SetStreams(pAppFonts->GetStreams());
m_pFontManager->SetOwnerCache(pMeasurerCache);
pMeasurerCache->SetCacheSize(1);
RELEASEOBJECT(m_pPDFDocument);
m_eError = errNone; m_eError = errNone;
GString* owner_pswd = NSStrings::CreateString(owner_password); GString* owner_pswd = NSStrings::CreateString(wsOwnerPassword);
GString* user_pswd = NSStrings::CreateString(user_password); GString* user_pswd = NSStrings::CreateString(wsUserPassword);
Object obj; Object obj;
obj.initNull(); obj.initNull();
// будет освобожден в деструкторе PDFDoc // будет освобожден в деструкторе PDFDoc
BaseStream *str = new MemStream((char*)data, 0, length, &obj); BaseStream *str = new MemStream((char*)data, 0, length, &obj);
m_pPDFDocument = new PDFDoc(str, owner_pswd, user_pswd); CPdfReaderContext* pContext = new CPdfReaderContext();
m_nFileLength = length; pContext->m_pDocument = new PDFDoc(str, owner_pswd, user_pswd);
pContext->m_pFontList = new PdfReader::CPdfFontList();
PDFDoc* pDoc = pContext->m_pDocument;
delete owner_pswd; delete owner_pswd;
delete user_pswd; delete user_pswd;
m_eError = m_pPDFDocument ? m_pPDFDocument->getErrorCode() : errMemory; m_nFileLength = length;
if (!m_pPDFDocument || !m_pPDFDocument->isOk()) m_eError = pDoc ? pDoc->getErrorCode() : errMemory;
if (!pDoc || !pDoc->isOk())
{ {
RELEASEOBJECT(m_pPDFDocument); Clear();
return false; return false;
} }
m_pFontList->Clear(); std::map<std::wstring, std::wstring> mFonts = PdfReader::CAnnotFonts::GetAllFonts(pDoc, m_pFontManager, pContext->m_pFontList);
std::map<std::wstring, std::wstring> mFonts = PdfReader::CAnnotFonts::GetAllFonts(m_pPDFDocument, m_pFontManager, m_pFontList);
m_mFonts.insert(mFonts.begin(), mFonts.end()); m_mFonts.insert(mFonts.begin(), mFonts.end());
return true; return true;
@ -455,7 +452,7 @@ bool CPdfReader::AddFromMemory(BYTE* pData, DWORD nLength, const std::wstring& w
} }
void CPdfReader::Close() void CPdfReader::Close()
{ {
RELEASEOBJECT(m_pPDFDocument); Clear();
m_mFonts.clear(); m_mFonts.clear();
} }
void CPdfReader::SetParams(COfficeDrawingPageParams* pParams) void CPdfReader::SetParams(COfficeDrawingPageParams* pParams)
@ -468,37 +465,64 @@ void CPdfReader::SetParams(COfficeDrawingPageParams* pParams)
globalParams->setDrawAnnotations(bDraw); globalParams->setDrawAnnotations(bDraw);
} }
int CPdfReader::GetPageIndex(int nPageIndex, PDFDoc** pDoc, PdfReader::CPdfFontList** pFontList)
{
int nTotalPages = 0;
for (CPdfReaderContext* pPDFContext : m_vPDFContext)
{
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
int nPages = pPDFContext->m_pDocument->getNumPages();
if (nPageIndex < nTotalPages + nPages)
{
if (pDoc)
*pDoc = pPDFContext->m_pDocument;
if (pFontList)
*pFontList = pPDFContext->m_pFontList;
return nPageIndex - nTotalPages + 1;
}
nTotalPages += nPages;
}
return -1;
}
int CPdfReader::GetError() int CPdfReader::GetError()
{ {
if (!m_pPDFDocument) if (m_vPDFContext.empty())
return m_eError; return m_eError;
if (m_pPDFDocument->isOk()) for (CPdfReaderContext* pPDFContext : m_vPDFContext)
return 0; {
PDFDoc* pDoc = pPDFContext->m_pDocument;
if (!pDoc)
return m_eError;
return m_pPDFDocument->getErrorCode(); if (pDoc->isOk() == gFalse)
return pDoc->getErrorCode();
}
return 0;
} }
void CPdfReader::GetPageInfo(int _nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY) void CPdfReader::GetPageInfo(int _nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY)
{ {
int nPageIndex = _nPageIndex + 1; PDFDoc* pDoc = NULL;
int nPageIndex = GetPageIndex(_nPageIndex, &pDoc);
if (!m_pPDFDocument) if (nPageIndex < 0 || !pDoc)
return; return;
#ifdef BUILDING_WASM_MODULE #ifdef BUILDING_WASM_MODULE
*pdWidth = m_pPDFDocument->getPageCropWidth(nPageIndex); *pdWidth = pDoc->getPageCropWidth(nPageIndex);
*pdHeight = m_pPDFDocument->getPageCropHeight(nPageIndex); *pdHeight = pDoc->getPageCropHeight(nPageIndex);
#else #else
int nRotate = m_pPDFDocument->getPageRotate(nPageIndex); int nRotate = pDoc->getPageRotate(nPageIndex);
if (nRotate % 180 == 0) if (nRotate % 180 == 0)
{ {
*pdWidth = m_pPDFDocument->getPageCropWidth(nPageIndex); *pdWidth = pDoc->getPageCropWidth(nPageIndex);
*pdHeight = m_pPDFDocument->getPageCropHeight(nPageIndex); *pdHeight = pDoc->getPageCropHeight(nPageIndex);
} }
else else
{ {
*pdHeight = m_pPDFDocument->getPageCropWidth(nPageIndex); *pdHeight = pDoc->getPageCropWidth(nPageIndex);
*pdWidth = m_pPDFDocument->getPageCropHeight(nPageIndex); *pdWidth = pDoc->getPageCropHeight(nPageIndex);
} }
#endif #endif
@ -507,29 +531,40 @@ void CPdfReader::GetPageInfo(int _nPageIndex, double* pdWidth, double* pdHeight,
} }
int CPdfReader::GetRotate(int _nPageIndex) int CPdfReader::GetRotate(int _nPageIndex)
{ {
if (!m_pPDFDocument) PDFDoc* pDoc = NULL;
int nPageIndex = GetPageIndex(_nPageIndex, &pDoc);
if (nPageIndex < 0 || !pDoc)
return 0; return 0;
return m_pPDFDocument->getPageRotate(_nPageIndex + 1); return pDoc->getPageRotate(nPageIndex);
} }
int CPdfReader::GetMaxRefID() int CPdfReader::GetMaxRefID()
{ {
if (!m_pPDFDocument) int nMaxRefID = 0;
return 0; for (CPdfReaderContext* pPDFContext : m_vPDFContext)
return m_pPDFDocument->getXRef()->getNumObjects(); {
if (!pPDFContext || !pPDFContext->m_pDocument || !pPDFContext->m_pDocument->getXRef())
continue;
nMaxRefID = std::max(nMaxRefID, pPDFContext->m_pDocument->getXRef()->getNumObjects());
}
return nMaxRefID;
} }
bool CPdfReader::ValidMetaData() bool CPdfReader::ValidMetaData()
{ {
if (!m_pPDFDocument) if (m_vPDFContext.empty() || m_vPDFContext.size() != 1)
return false; return false;
XRef* xref = m_pPDFDocument->getXRef(); CPdfReaderContext* pPDFContext = m_vPDFContext.front();
Object oMeta, oType, oID; if (!pPDFContext || !pPDFContext->m_pDocument)
if (!xref->fetch(1, 0, &oMeta)->isStream() || !oMeta.streamGetDict()->lookup("Type", &oType)->isName("MetaOForm") || !oMeta.streamGetDict()->lookup("ID", &oID)->isString()) return false;
XRef* xref = pPDFContext->m_pDocument->getXRef();
Object oMeta, oID;
if (!xref->fetch(1, 0, &oMeta)->isStream("MetaOForm") || !oMeta.streamGetDict()->lookup("ID", &oID)->isString())
{ {
oMeta.free(); oType.free(); oID.free(); oMeta.free(); oID.free();
return false; return false;
} }
oMeta.free(); oType.free(); oMeta.free();
Object oTID, oID2; Object oTID, oID2;
Object* pTrailerDict = xref->getTrailerDict(); Object* pTrailerDict = xref->getTrailerDict();
@ -546,25 +581,25 @@ bool CPdfReader::ValidMetaData()
} }
void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* pbBreak) void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* pbBreak)
{ {
if (m_pPDFDocument && pRenderer) PDFDoc* pDoc = NULL;
{ PdfReader::CPdfFontList* pFontList = NULL;
PdfReader::RendererOutputDev oRendererOut(pRenderer, m_pFontManager, m_pFontList); int nPageIndex = GetPageIndex(_nPageIndex, &pDoc, &pFontList);
oRendererOut.NewPDF(m_pPDFDocument->getXRef()); if (nPageIndex < 0 || !pDoc || !pFontList)
oRendererOut.SetBreak(pbBreak); return;
int nRotate = 0;
PdfReader::RendererOutputDev oRendererOut(pRenderer, m_pFontManager, pFontList);
oRendererOut.NewPDF(pDoc->getXRef());
oRendererOut.SetBreak(pbBreak);
int nRotate = 0;
#ifdef BUILDING_WASM_MODULE #ifdef BUILDING_WASM_MODULE
nRotate = -m_pPDFDocument->getPageRotate(_nPageIndex + 1); nRotate = -pDoc->getPageRotate(nPageIndex);
#endif #endif
m_pPDFDocument->displayPage(&oRendererOut, _nPageIndex + 1, 72.0, 72.0, nRotate, gFalse, gTrue, gFalse); pDoc->displayPage(&oRendererOut, nPageIndex, 72.0, 72.0, nRotate, gFalse, gTrue, gFalse);
}
} }
void CPdfReader::SetTempDirectory(const std::wstring& wsTempFolder) void CPdfReader::SetTempDirectory(const std::wstring& wsTempFolder)
{ {
if (!m_wsTempFolder.empty()) if (!m_wsTempFolder.empty())
{
NSDirectory::DeleteDirectory(m_wsTempFolder); NSDirectory::DeleteDirectory(m_wsTempFolder);
m_wsTempFolder = wsTempFolder;
}
if (!wsTempFolder.empty()) if (!wsTempFolder.empty())
{ {
@ -591,7 +626,7 @@ std::wstring CPdfReader::GetTempDirectory()
} }
std::wstring CPdfReader::ToXml(const std::wstring& wsFilePath, bool isPrintStream) std::wstring CPdfReader::ToXml(const std::wstring& wsFilePath, bool isPrintStream)
{ {
XMLConverter oConverter(m_pPDFDocument->getXRef(), isPrintStream); XMLConverter oConverter(m_vPDFContext.front()->m_pDocument->getXRef(), isPrintStream);
std::wstring wsXml = oConverter.GetXml(); std::wstring wsXml = oConverter.GetXml();
if (wsFilePath != L"") if (wsFilePath != L"")
@ -609,17 +644,24 @@ std::wstring CPdfReader::ToXml(const std::wstring& wsFilePath, bool isPrintStrea
std::wstring CPdfReader::GetInfo() std::wstring CPdfReader::GetInfo()
{ {
if (!m_pPDFDocument) std::wstring sRes;
return NULL; if (m_vPDFContext.empty())
XRef* xref = m_pPDFDocument->getXRef(); return sRes;
BaseStream* str = m_pPDFDocument->getBaseStream();
CPdfReaderContext* pPDFContext = m_vPDFContext.front();
if (!pPDFContext || !pPDFContext->m_pDocument)
return sRes;
PDFDoc* pDoc = pPDFContext->m_pDocument;
XRef* xref = pDoc->getXRef();
BaseStream* str = pDoc->getBaseStream();
if (!xref || !str) if (!xref || !str)
return NULL; return NULL;
std::wstring sRes = L"{"; sRes = L"{";
Object oInfo; Object oInfo;
if (m_pPDFDocument->getDocInfo(&oInfo)->isDict()) if (pDoc->getDocInfo(&oInfo)->isDict())
{ {
auto fDictLookup = [&oInfo](const char* sName, const wchar_t* wsName) auto fDictLookup = [&oInfo](const char* sName, const wchar_t* wsName)
{ {
@ -691,7 +733,7 @@ std::wstring CPdfReader::GetInfo()
} }
oInfo.free(); oInfo.free();
std::wstring version = std::to_wstring(m_pPDFDocument->getPDFVersion()); std::wstring version = std::to_wstring(pDoc->getPDFVersion());
std::wstring::size_type posDot = version.find('.'); std::wstring::size_type posDot = version.find('.');
if (posDot != std::wstring::npos) if (posDot != std::wstring::npos)
version.resize(posDot + 2); version.resize(posDot + 2);
@ -707,34 +749,46 @@ std::wstring CPdfReader::GetInfo()
sRes += L",\"PageHeight\":"; sRes += L",\"PageHeight\":";
sRes += std::to_wstring((int)(nH * 100)); sRes += std::to_wstring((int)(nH * 100));
sRes += L",\"NumberOfPages\":"; sRes += L",\"NumberOfPages\":";
sRes += std::to_wstring(m_pPDFDocument->getNumPages());
int nNumPages = 0;
for (CPdfReaderContext* pPDFContext : m_vPDFContext)
{
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
PDFDoc* pDoc = pPDFContext->m_pDocument;
nNumPages += pDoc->getNumPages();
}
sRes += std::to_wstring(nNumPages);
sRes += L",\"FastWebView\":"; sRes += L",\"FastWebView\":";
Object obj1, obj2, obj3, obj4, obj5, obj6;
bool bLinearized = false; bool bLinearized = false;
obj1.initNull(); if (m_vPDFContext.size() == 1)
Parser* parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(), gFalse, 0, &obj1)), gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && obj4.isDict())
{ {
obj4.dictLookup("Linearized", &obj5); Object obj1, obj2, obj3, obj4, obj5, obj6;
obj4.dictLookup("L", &obj6); obj1.initNull();
if (obj5.isNum() && obj5.getNum() > 0 && obj6.isNum()) Parser* parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(), gFalse, 0, &obj1)), gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && obj4.isDict())
{ {
unsigned long size = (unsigned long)obj6.getNum(); obj4.dictLookup("Linearized", &obj5);
bLinearized = size == m_nFileLength; if (obj5.isNum() && obj5.getNum() > 0 && obj4.dictLookup("L", &obj6)->isNum())
{
unsigned long size = (unsigned long)obj6.getNum();
bLinearized = size == m_nFileLength;
}
obj6.free();
obj5.free();
} }
obj6.free(); obj4.free();
obj5.free(); obj3.free();
obj2.free();
obj1.free();
delete parser;
} }
obj4.free();
obj3.free();
obj2.free();
obj1.free();
delete parser;
sRes += bLinearized ? L"true" : L"false"; sRes += bLinearized ? L"true" : L"false";
sRes += L",\"Tagged\":"; sRes += L",\"Tagged\":";
@ -827,9 +881,14 @@ void getBookmarks(PDFDoc* pdfDoc, OutlineItem* pOutlineItem, NSWasm::CData& out,
} }
BYTE* CPdfReader::GetStructure() BYTE* CPdfReader::GetStructure()
{ {
if (!m_pPDFDocument) if (m_vPDFContext.empty())
return NULL; return NULL;
Outline* pOutline = m_pPDFDocument->getOutline(); CPdfReaderContext* pPDFContext = m_vPDFContext.front();
if (!pPDFContext || !pPDFContext->m_pDocument)
return NULL;
PDFDoc* pDoc = pPDFContext->m_pDocument;
Outline* pOutline = pDoc->getOutline();
if (!pOutline) if (!pOutline)
return NULL; return NULL;
GList* pList = pOutline->getItems(); GList* pList = pOutline->getItems();
@ -842,7 +901,7 @@ BYTE* CPdfReader::GetStructure()
{ {
OutlineItem* pOutlineItem = (OutlineItem*)pList->get(i); OutlineItem* pOutlineItem = (OutlineItem*)pList->get(i);
if (pOutlineItem) if (pOutlineItem)
getBookmarks(m_pPDFDocument, pOutlineItem, oRes, 1); getBookmarks(pDoc, pOutlineItem, oRes, 1);
} }
oRes.WriteLen(); oRes.WriteLen();
@ -850,20 +909,21 @@ BYTE* CPdfReader::GetStructure()
oRes.ClearWithoutAttack(); oRes.ClearWithoutAttack();
return bRes; return bRes;
} }
BYTE* CPdfReader::GetLinks(int nPageIndex) BYTE* CPdfReader::GetLinks(int _nPageIndex)
{ {
if (!m_pPDFDocument || !m_pPDFDocument->getCatalog()) PDFDoc* pDoc = NULL;
int nPageIndex = GetPageIndex(_nPageIndex, &pDoc);
if (nPageIndex < 0 || !pDoc || !pDoc->getCatalog())
return NULL; return NULL;
nPageIndex++; Page* pPage = pDoc->getCatalog()->getPage(nPageIndex);
Page* pPage = m_pPDFDocument->getCatalog()->getPage(nPageIndex);
if (!pPage) if (!pPage)
return NULL; return NULL;
NSWasm::CPageLink oLinks; NSWasm::CPageLink oLinks;
// Гиперссылка // Гиперссылка
Links* pLinks = m_pPDFDocument->getLinks(nPageIndex); Links* pLinks = pDoc->getLinks(nPageIndex);
if (pLinks) if (pLinks)
{ {
PDFRectangle* cropBox = pPage->getCropBox(); PDFRectangle* cropBox = pPage->getCropBox();
@ -888,14 +948,14 @@ BYTE* CPdfReader::GetLinks(int nPageIndex)
if (kind == actionGoTo) if (kind == actionGoTo)
{ {
str = ((LinkGoTo*)pLinkAction)->getNamedDest(); str = ((LinkGoTo*)pLinkAction)->getNamedDest();
LinkDest* pLinkDest = str ? m_pPDFDocument->findDest(str) : ((LinkGoTo*)pLinkAction)->getDest()->copy(); LinkDest* pLinkDest = str ? pDoc->findDest(str) : ((LinkGoTo*)pLinkAction)->getDest()->copy();
if (pLinkDest) if (pLinkDest)
{ {
int pg; int pg;
if (pLinkDest->isPageRef()) if (pLinkDest->isPageRef())
{ {
Ref pageRef = pLinkDest->getPageRef(); Ref pageRef = pLinkDest->getPageRef();
pg = m_pPDFDocument->findPage(pageRef.num, pageRef.gen); pg = pDoc->findPage(pageRef.num, pageRef.gen);
} }
else else
pg = pLinkDest->getPageNum(); pg = pLinkDest->getPageNum();
@ -904,7 +964,7 @@ BYTE* CPdfReader::GetLinks(int nPageIndex)
std::string sLink = "#" + std::to_string(pg - 1); std::string sLink = "#" + std::to_string(pg - 1);
str = new GString(sLink.c_str()); str = new GString(sLink.c_str());
dy = m_pPDFDocument->getPageCropHeight(pg) - pLinkDest->getTop(); dy = pDoc->getPageCropHeight(pg) - pLinkDest->getTop();
} }
else else
str = NULL; str = NULL;
@ -919,8 +979,8 @@ BYTE* CPdfReader::GetLinks(int nPageIndex)
if (!str->cmp("NextPage")) if (!str->cmp("NextPage"))
{ {
pg = nPageIndex + 1; pg = nPageIndex + 1;
if (pg > m_pPDFDocument->getNumPages()) if (pg > pDoc->getNumPages())
pg = m_pPDFDocument->getNumPages(); pg = pDoc->getNumPages();
} }
else if (!str->cmp("PrevPage")) else if (!str->cmp("PrevPage"))
{ {
@ -929,7 +989,7 @@ BYTE* CPdfReader::GetLinks(int nPageIndex)
pg = 1; pg = 1;
} }
else if (!str->cmp("LastPage")) else if (!str->cmp("LastPage"))
pg = m_pPDFDocument->getNumPages(); pg = pDoc->getNumPages();
std::string sLink = "#" + std::to_string(pg - 1); std::string sLink = "#" + std::to_string(pg - 1);
str = new GString(sLink.c_str()); str = new GString(sLink.c_str());
@ -950,8 +1010,8 @@ BYTE* CPdfReader::GetLinks(int nPageIndex)
TextOutputControl textOutControl; TextOutputControl textOutControl;
textOutControl.mode = textOutReadingOrder; textOutControl.mode = textOutReadingOrder;
TextOutputDev* pTextOut = new TextOutputDev(NULL, &textOutControl, gFalse); TextOutputDev* pTextOut = new TextOutputDev(NULL, &textOutControl, gFalse);
m_pPDFDocument->displayPage(pTextOut, nPageIndex, 72.0, 72.0, nRotate, gFalse, gTrue, gFalse); pDoc->displayPage(pTextOut, nPageIndex, 72.0, 72.0, nRotate, gFalse, gTrue, gFalse);
m_pPDFDocument->processLinks(pTextOut, nPageIndex); pDoc->processLinks(pTextOut, nPageIndex);
TextWordList* pWordList = pTextOut->makeWordList(); TextWordList* pWordList = pTextOut->makeWordList();
for (int i = 0; i < pWordList->getLength(); i++) for (int i = 0; i < pWordList->getLength(); i++)
{ {

View File

@ -100,7 +100,7 @@ public:
private: private:
void Clear(); void Clear();
void ReadFonts(); int GetPageIndex(int nPageIndex, PDFDoc** pDoc = NULL, PdfReader::CPdfFontList** pFontList = NULL);
std::wstring m_wsTempFolder; std::wstring m_wsTempFolder;
NSFonts::IFontManager* m_pFontManager; NSFonts::IFontManager* m_pFontManager;