/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "PDFiumEngineShim.h" #include "private/pprio.h" typedef void (STDCALL *FPDF_InitLibrary_Pfn)(); typedef void (STDCALL *FPDF_DestroyLibrary_Pfn)(); typedef FPDF_DOCUMENT (STDCALL *FPDF_LoadDocument_Pfn)(FPDF_STRING file_path, FPDF_BYTESTRING password); typedef FPDF_DOCUMENT (STDCALL *FPDF_LoadCustomDocument_Pfn)(FPDF_FILEACCESS* pFileAccess, FPDF_BYTESTRING password); typedef void(STDCALL *FPDF_CloseDocument_Pfn)(FPDF_DOCUMENT aDocument); typedef int (STDCALL *FPDF_GetPageCount_Pfn)(FPDF_DOCUMENT aDocument); typedef FPDF_PAGE (STDCALL *FPDF_LoadPage_Pfn)(FPDF_DOCUMENT aDocument, int aPageIndex); typedef void (STDCALL *FPDF_ClosePage_Pfn)(FPDF_PAGE aPage); typedef void (STDCALL *FPDF_RenderPage_Pfn)(HDC aDC, FPDF_PAGE aPage, int aStartX, int aStartY, int aSizeX, int aSizeY, int aRotate, int aFlags); namespace mozilla { namespace widget { static PDFiumEngineShim* sPDFiumEngineShim; struct PDFFunctionPointerTable { PDFFunctionPointerTable() : mFPDF_InitLibrary(nullptr) , mFPDF_DestroyLibrary(nullptr) , mFPDF_CloseDocument(nullptr) , mFPDF_GetPageCount(nullptr) , mFPDF_LoadPage(nullptr) , mFPDF_ClosePage(nullptr) , mFPDF_RenderPage(nullptr) { } FPDF_InitLibrary_Pfn mFPDF_InitLibrary; FPDF_DestroyLibrary_Pfn mFPDF_DestroyLibrary; FPDF_LoadDocument_Pfn mFPDF_LoadDocument; FPDF_LoadCustomDocument_Pfn mFPDF_LoadCustomDocument; FPDF_CloseDocument_Pfn mFPDF_CloseDocument; FPDF_GetPageCount_Pfn mFPDF_GetPageCount; FPDF_LoadPage_Pfn mFPDF_LoadPage; FPDF_ClosePage_Pfn mFPDF_ClosePage; FPDF_RenderPage_Pfn mFPDF_RenderPage; }; /* static */ already_AddRefed PDFiumEngineShim::GetInstanceOrNull() { RefPtr inst = sPDFiumEngineShim; if (!inst) { inst = new PDFiumEngineShim(); if (!inst->Init(NS_LITERAL_STRING("pdfium.dll"))) { inst = nullptr; } sPDFiumEngineShim = inst.get(); } return inst.forget(); } /* static */ already_AddRefed PDFiumEngineShim::GetInstanceOrNull(const nsString& aLibrary) { RefPtr shim = new PDFiumEngineShim(); if (!shim->Init(aLibrary)) { return nullptr; } return shim.forget(); } PDFiumEngineShim::PDFiumEngineShim() : mTable(MakeUnique()) , mInitialized(false) , mPRLibrary(nullptr) { } PDFiumEngineShim::~PDFiumEngineShim() { if (mInitialized) { mTable->mFPDF_DestroyLibrary(); } sPDFiumEngineShim = nullptr; if (mPRLibrary) { PR_UnloadLibrary(mPRLibrary); } } bool PDFiumEngineShim::Init(const nsString& aLibrary) { if (mInitialized) { return true; } PRLibSpec libSpec; libSpec.type = PR_LibSpec_PathnameU; libSpec.value.pathname_u = aLibrary.get(); mPRLibrary = PR_LoadLibraryWithFlags(libSpec, 0); NS_ENSURE_TRUE(mPRLibrary, false); mTable->mFPDF_InitLibrary = (FPDF_InitLibrary_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_InitLibrary"); NS_ENSURE_TRUE(mTable->mFPDF_InitLibrary, false); mTable->mFPDF_DestroyLibrary = (FPDF_DestroyLibrary_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_DestroyLibrary"); NS_ENSURE_TRUE(mTable->mFPDF_DestroyLibrary, false); mTable->mFPDF_LoadDocument = (FPDF_LoadDocument_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_LoadDocument"); NS_ENSURE_TRUE(mTable->mFPDF_LoadDocument, false); mTable->mFPDF_LoadCustomDocument = (FPDF_LoadCustomDocument_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_LoadCustomDocument"); NS_ENSURE_TRUE(mTable->mFPDF_LoadCustomDocument, false); mTable->mFPDF_CloseDocument = (FPDF_CloseDocument_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_CloseDocument"); NS_ENSURE_TRUE(mTable->mFPDF_CloseDocument, false); mTable->mFPDF_GetPageCount = (FPDF_GetPageCount_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_GetPageCount"); NS_ENSURE_TRUE(mTable->mFPDF_GetPageCount, false); mTable->mFPDF_LoadPage = (FPDF_LoadPage_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_LoadPage"); NS_ENSURE_TRUE(mTable->mFPDF_LoadPage, false); mTable->mFPDF_ClosePage = (FPDF_ClosePage_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_ClosePage"); NS_ENSURE_TRUE(mTable->mFPDF_ClosePage, false); mTable->mFPDF_RenderPage = (FPDF_RenderPage_Pfn)PR_FindFunctionSymbol(mPRLibrary, "FPDF_RenderPage"); NS_ENSURE_TRUE(mTable->mFPDF_RenderPage, false); mTable->mFPDF_InitLibrary(); mInitialized = true; return true; } FPDF_DOCUMENT PDFiumEngineShim::LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING aPassword) { MOZ_ASSERT(mInitialized); return mTable->mFPDF_LoadDocument(file_path, aPassword); } FPDF_DOCUMENT PDFiumEngineShim::LoadDocument(PRFileDesc* aPrfile, FPDF_BYTESTRING aPassword) { MOZ_ASSERT(mInitialized && aPrfile); PROffset32 fileLength = PR_Seek64(aPrfile, 0, PR_SEEK_END); if (fileLength == -1) { NS_WARNING("Failed to access the given FD."); return nullptr; } FPDF_FILEACCESS fileAccess; fileAccess.m_FileLen = static_cast(fileLength); fileAccess.m_Param = reinterpret_cast(aPrfile); fileAccess.m_GetBlock = [](void* param, unsigned long pos, unsigned char* buf, unsigned long size) { PRFileDesc* prfile = reinterpret_cast(param); if (PR_Seek64(prfile, pos, PR_SEEK_SET) != pos) { return 0; } if (PR_Read(prfile, buf, size) <= 0) { return 0; } return 1; }; return mTable->mFPDF_LoadCustomDocument(&fileAccess, aPassword); } void PDFiumEngineShim::CloseDocument(FPDF_DOCUMENT aDocument) { MOZ_ASSERT(mInitialized); mTable->mFPDF_CloseDocument(aDocument); } int PDFiumEngineShim::GetPageCount(FPDF_DOCUMENT aDocument) { MOZ_ASSERT(mInitialized); return mTable->mFPDF_GetPageCount(aDocument); } FPDF_PAGE PDFiumEngineShim::LoadPage(FPDF_DOCUMENT aDocument, int aPageIndex) { MOZ_ASSERT(mInitialized); return mTable->mFPDF_LoadPage(aDocument, aPageIndex); } void PDFiumEngineShim::ClosePage(FPDF_PAGE aPage) { MOZ_ASSERT(mInitialized); mTable->mFPDF_ClosePage(aPage); } void PDFiumEngineShim::RenderPage(HDC aDC, FPDF_PAGE aPage, int aStartX, int aStartY, int aSizeX, int aSizeY, int aRotate, int aFlags) { MOZ_ASSERT(mInitialized); mTable->mFPDF_RenderPage(aDC, aPage, aStartX, aStartY, aSizeX, aSizeY, aRotate, aFlags); } } // namespace widget } // namespace mozilla