1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include "qpdfdocument.h"
#include "qpdfdocument_p.h"
#include <QFile>
#include <QIODevice>
#include <QMutex>
static int libraryRefCount;
static QMutex libraryInitializerMutex;
// PDFium stores the error code when loading a document in a global
// variable, but that is only set from the FPDF_Load*Document functions.
// Therefore this mutex serializes access to the loading.
static QMutex documentLoadMutex;
QPdfDocumentPrivate::QPdfDocumentPrivate()
: doc(0)
{
{
QMutexLocker lock(&libraryInitializerMutex);
if (libraryRefCount == 0)
FPDF_InitLibrary();
++libraryRefCount;
}
}
QPdfDocumentPrivate::~QPdfDocumentPrivate()
{
if (doc)
FPDF_CloseDocument(doc);
doc = 0;
{
QMutexLocker lock(&libraryInitializerMutex);
if (!--libraryRefCount)
FPDF_DestroyLibrary();
}
}
QPdfDocument::QPdfDocument(QObject *parent)
: QObject(parent)
, d(new QPdfDocumentPrivate)
{
}
QPdfDocument::~QPdfDocument()
{
}
static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size)
{
QIODevice *dev = reinterpret_cast<QIODevice*>(param);
dev->seek(position);
return dev->read(reinterpret_cast<char *>(pBuf), size);
}
QPdfDocument::Error QPdfDocument::load(const QString &fileName, const QString &password)
{
if (d->doc)
FPDF_CloseDocument(d->doc);
QFile *file = new QFile(fileName);
d->device.reset(file);
if (!d->device->open(QIODevice::ReadOnly))
return FileNotFoundError;
FPDF_FILEACCESS access;
access.m_FileLen = file->size();
access.m_GetBlock = fpdf_GetBlock;
access.m_Param = d->device.data();
d->password = password.toUtf8();
QMutexLocker loadLocker(&documentLoadMutex);
d->doc = FPDF_LoadCustomDocument(&access, d->password.constData());
switch (FPDF_GetLastError()) {
case FPDF_ERR_SUCCESS: return NoError;
case FPDF_ERR_UNKNOWN: return UnknownError;
case FPDF_ERR_FILE: return FileNotFoundError;
case FPDF_ERR_FORMAT: return InvalidFileFormatError;
case FPDF_ERR_PASSWORD: return IncorrectPasswordError;
case FPDF_ERR_SECURITY: return UnsupportedSecuritySchemeError;
default:
Q_UNREACHABLE();
}
return UnknownError;
}
int QPdfDocument::pageCount() const
{
if (!d->doc)
return 0;
return FPDF_GetPageCount(d->doc);
}
QSizeF QPdfDocument::pageSize(int page) const
{
QSizeF result;
if (!d->doc)
return result;
FPDF_GetPageSizeByIndex(d->doc, page, &result.rwidth(), &result.rheight());
return result;
}
QImage QPdfDocument::render(int page, const QSizeF &pageSize)
{
if (!d->doc)
return QImage();
FPDF_PAGE pdfPage = FPDF_LoadPage(d->doc, page);
if (!pdfPage)
return QImage();
QImage result(pageSize.toSize(), QImage::Format_ARGB32);
result.fill(Qt::transparent);
FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(result.width(), result.height(), FPDFBitmap_BGRA, result.bits(), result.bytesPerLine());
FPDF_RenderPageBitmap(bitmap, pdfPage, 0, 0, result.width(), result.height(), 0, 0);
FPDFBitmap_Destroy(bitmap);
return result;
}
|