/* -*- 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> PDFiumEngineShim::GetInstanceOrNull() {
RefPtr<PDFiumEngineShim> 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> PDFiumEngineShim::GetInstanceOrNull(
const nsString &aLibrary) {
RefPtr<PDFiumEngineShim> shim = new PDFiumEngineShim();
if (!shim->Init(aLibrary)) {
return nullptr;
}
return shim.forget();
}
PDFiumEngineShim::PDFiumEngineShim()
: mTable(MakeUnique<PDFFunctionPointerTable>()),
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<unsigned long>(fileLength);
fileAccess.m_Param = reinterpret_cast<void *>(aPrfile);
fileAccess.m_GetBlock = [](void *param, unsigned long pos, unsigned char *buf,
unsigned long size) {
PRFileDesc *prfile = reinterpret_cast<PRFileDesc *>(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