yacreader/common/pdf_comic.cpp
Luis Ángel San Martín Rodríguez f29c3a4f96 BUMP minimum render size for PDF pages
2024-06-20 17:12:03 +02:00

136 lines
3.2 KiB
C++

#include "comic.h"
#include "pdf_comic.h"
#if defined USE_PDFIUM && !defined NO_PDF
int pdfRead(void *param,
unsigned long position,
unsigned char *pBuf,
unsigned long size)
{
QFile *file = static_cast<QFile *>(param);
file->seek(position);
qint64 numBytesRead = file->read(reinterpret_cast<char *>(pBuf), size);
if (numBytesRead > 0) {
return numBytesRead;
}
return 0;
}
// pdfium is not threadsafe
// We need to use mutex locking & refcounting to avoid crashes
int PdfiumComic::refcount = 0;
QMutex PdfiumComic::pdfmutex;
PdfiumComic::PdfiumComic()
{
QMutexLocker locker(&pdfmutex);
if (++refcount == 1) {
FPDF_InitLibrary();
}
}
PdfiumComic::~PdfiumComic()
{
QMutexLocker locker(&pdfmutex);
if (doc) {
FPDF_CloseDocument(doc);
}
if (--refcount == 0) {
FPDF_DestroyLibrary();
}
}
bool PdfiumComic::openComic(const QString &path)
{
pdfFile.setFileName(path);
if (pdfFile.open(QIODevice::ReadOnly) == false) {
qDebug() << "unable to open file : " << path;
return false;
}
fileAccess.m_FileLen = pdfFile.size();
fileAccess.m_GetBlock = pdfRead;
fileAccess.m_Param = &pdfFile;
QMutexLocker lock(&pdfmutex);
doc = FPDF_LoadCustomDocument(&fileAccess, NULL);
if (doc) {
return true;
} else {
qDebug() << FPDF_GetLastError();
return false;
}
}
void PdfiumComic::closeComic()
{
QMutexLocker locker(&pdfmutex);
FPDF_CloseDocument(doc);
}
unsigned int PdfiumComic::numPages()
{
if (doc) {
QMutexLocker locker(&pdfmutex);
return FPDF_GetPageCount(doc);
} else {
return 0; //-1?
}
}
QImage PdfiumComic::getPage(const int page)
{
if (!doc) {
return QImage();
}
QImage image;
FPDF_PAGE pdfpage;
FPDF_BITMAP bitmap;
QMutexLocker locker(&pdfmutex);
pdfpage = FPDF_LoadPage(doc, page);
if (!pdfpage) {
// TODO report error
qDebug() << FPDF_GetLastError();
return QImage();
}
// TODO: make target DPI configurable
// TODO: max render size too
QSize pagesize((FPDF_GetPageWidth(pdfpage) / 72) * 150,
(FPDF_GetPageHeight(pdfpage) / 72) * 150);
auto maxSize = 4096;
if (pagesize.width() > maxSize || pagesize.height() > maxSize) {
pagesize.scale(maxSize, maxSize, Qt::KeepAspectRatio);
}
auto minSize = 2560;
if (pagesize.width() < minSize || pagesize.height() < minSize) {
pagesize.scale(minSize, minSize, Qt::KeepAspectRatio);
}
image = QImage(pagesize, QImage::Format_ARGB32); // QImage::Format_RGBX8888);
if (image.isNull()) {
// TODO report OOM error
qDebug() << "Image too large, OOM";
return image;
}
image.fill(0xFFFFFFFF);
bitmap = FPDFBitmap_CreateEx(image.width(), image.height(), FPDFBitmap_BGRA, image.scanLine(0), image.bytesPerLine());
// TODO: make render flags costumizable
FPDF_RenderPageBitmap(bitmap, pdfpage, 0, 0, image.width(), image.height(), 0, (FPDF_LCD_TEXT));
FPDFBitmap_Destroy(bitmap);
FPDF_ClosePage(pdfpage);
return image;
}
#endif // USE_PDFIUM