|
|
@ -19,6 +19,13 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include <frameworks/UBPlatformUtils.h> |
|
|
|
#include <frameworks/UBPlatformUtils.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <splash/SplashBitmap.h> |
|
|
|
|
|
|
|
#include <xpdf/Object.h> |
|
|
|
|
|
|
|
#include <xpdf/GlobalParams.h> |
|
|
|
|
|
|
|
#include <xpdf/SplashOutputDev.h> |
|
|
|
|
|
|
|
#include <xpdf/PDFDoc.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "core/memcheck.h" |
|
|
|
#include "core/memcheck.h" |
|
|
|
|
|
|
|
|
|
|
|
QAtomicInt XPDFRenderer::sInstancesCount = 0; |
|
|
|
QAtomicInt XPDFRenderer::sInstancesCount = 0; |
|
|
@ -37,13 +44,7 @@ XPDFRenderer::XPDFRenderer(const QString &filename) |
|
|
|
|
|
|
|
|
|
|
|
mDocument = new PDFDoc(new GString(filename.toUtf8().data()), 0, 0, 0); // the filename GString is deleted on PDFDoc desctruction
|
|
|
|
mDocument = new PDFDoc(new GString(filename.toUtf8().data()), 0, 0, 0); // the filename GString is deleted on PDFDoc desctruction
|
|
|
|
sInstancesCount.ref(); |
|
|
|
sInstancesCount.ref(); |
|
|
|
bThumbGenerated = false; |
|
|
|
|
|
|
|
bPagesGenerated = false; |
|
|
|
|
|
|
|
mPagesMap.clear(); |
|
|
|
|
|
|
|
mThumbs.clear(); |
|
|
|
|
|
|
|
mThumbMap.clear(); |
|
|
|
|
|
|
|
mScaleX = 0.0; |
|
|
|
|
|
|
|
mScaleY = 0.0; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
XPDFRenderer::~XPDFRenderer() |
|
|
|
XPDFRenderer::~XPDFRenderer() |
|
|
@ -134,114 +135,47 @@ int XPDFRenderer::pageRotation(int pageNumber) const |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void XPDFRenderer::render(QPainter *p, int pageNumber, const QRectF &bounds) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (isValid()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
qreal xscale = p->worldTransform().m11(); |
|
|
|
|
|
|
|
qreal yscale = p->worldTransform().m22(); |
|
|
|
|
|
|
|
bool bZoomChanged = false; |
|
|
|
|
|
|
|
bool bFirstThumbnail = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(fabs(mScaleX - xscale) > 0.1 || fabs(mScaleY - yscale) > 0.1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mScaleX = xscale; |
|
|
|
|
|
|
|
mScaleY = yscale; |
|
|
|
|
|
|
|
bZoomChanged = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// First verify if the thumbnails and the pages are generated
|
|
|
|
void XPDFRenderer::render(QPainter *p, int pageNumber, const QRectF &bounds) |
|
|
|
if(!bThumbGenerated) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if(pageNumber == 1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
bFirstThumbnail = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!mThumbMap[pageNumber - 1]) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate the thumbnail
|
|
|
|
|
|
|
|
mThumbs << *createPDFImage(pageNumber, xscale, yscale, bounds); |
|
|
|
|
|
|
|
mThumbMap[pageNumber - 1] = true; |
|
|
|
|
|
|
|
if(pageNumber == mDocument->getNumPages()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
bThumbGenerated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(!bPagesGenerated || bZoomChanged) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if(!mPagesMap[pageNumber - 1] || bZoomChanged) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Generate the page
|
|
|
|
|
|
|
|
mNumPageToPageMap[pageNumber] = *createPDFImage(pageNumber, xscale, yscale, bounds); |
|
|
|
|
|
|
|
mPagesMap[pageNumber - 1] = true; |
|
|
|
|
|
|
|
if(mPagesMap.size() == mDocument->getNumPages()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
bPagesGenerated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QImage pdfImage; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!bThumbGenerated || bFirstThumbnail) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pdfImage = mThumbs.at(pageNumber - 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pdfImage = mNumPageToPageMap[pageNumber]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QTransform savedTransform = p->worldTransform(); |
|
|
|
|
|
|
|
p->resetTransform(); |
|
|
|
|
|
|
|
QTime t; |
|
|
|
|
|
|
|
t.start(); |
|
|
|
|
|
|
|
p->drawImage(QPointF(savedTransform.dx() + mSliceX, savedTransform.dy() + mSliceY), pdfImage); |
|
|
|
|
|
|
|
//qDebug() << "XPDFRenderer::render(...) execution time: " << t.elapsed() << "ms";
|
|
|
|
|
|
|
|
p->setWorldTransform(savedTransform); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QImage* XPDFRenderer::createPDFImage(int pageNumber, const qreal xscale, const qreal yscale, const QRectF &bounds) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
QImage* img = new QImage(); |
|
|
|
|
|
|
|
if (isValid()) |
|
|
|
if (isValid()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
SplashColor paperColor = {0xFF, 0xFF, 0xFF}; // white
|
|
|
|
SplashColor paperColor = {0xFF, 0xFF, 0xFF}; // white
|
|
|
|
mSplash = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); |
|
|
|
SplashOutputDev splash(splashModeRGB8, 1, gFalse, paperColor); |
|
|
|
mSplash->startDoc(mDocument->getXRef()); |
|
|
|
splash.startDoc(mDocument->getXRef()); |
|
|
|
int hResolution = 72; |
|
|
|
int hResolution = 72; |
|
|
|
int vResolution = 72; |
|
|
|
int vResolution = 72; |
|
|
|
int rotation = 0; // in degrees (get it from the worldTransform if we want to support rotation)
|
|
|
|
int rotation = 0; // in degrees (get it from the worldTransform if we want to support rotation)
|
|
|
|
GBool useMediaBox = gFalse; |
|
|
|
GBool useMediaBox = gFalse; |
|
|
|
GBool crop = gTrue; |
|
|
|
GBool crop = gTrue; |
|
|
|
GBool printing = gFalse; |
|
|
|
GBool printing = gFalse; |
|
|
|
const qreal xScale = xscale; |
|
|
|
const qreal xScale = p->worldTransform().m11(); |
|
|
|
const qreal yScale = yscale; |
|
|
|
const qreal yScale = p->worldTransform().m22(); |
|
|
|
mSliceX = 0.; |
|
|
|
qreal sliceX = 0.; |
|
|
|
mSliceY = 0.; |
|
|
|
qreal sliceY = 0.; |
|
|
|
|
|
|
|
|
|
|
|
if (bounds.isNull()) |
|
|
|
if (bounds.isNull()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mDocument->displayPage(mSplash, pageNumber, hResolution * xScale, vResolution * yScale, |
|
|
|
mDocument->displayPage(&splash, pageNumber, hResolution * xScale, vResolution * yScale, |
|
|
|
rotation, useMediaBox, crop, printing); |
|
|
|
rotation, useMediaBox, crop, printing); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
mSliceX = bounds.x() * xScale; |
|
|
|
sliceX = bounds.x() * xScale; |
|
|
|
mSliceY = bounds.y() * yScale; |
|
|
|
sliceY = bounds.y() * yScale; |
|
|
|
qreal sliceW = bounds.width() * xScale; |
|
|
|
qreal sliceW = bounds.width() * xScale; |
|
|
|
qreal sliceH = bounds.height() * yScale; |
|
|
|
qreal sliceH = bounds.height() * yScale; |
|
|
|
|
|
|
|
|
|
|
|
mDocument->displayPageSlice(mSplash, pageNumber, hResolution * xScale, vResolution * yScale, |
|
|
|
mDocument->displayPageSlice(&splash, pageNumber, hResolution * xScale, vResolution * yScale, |
|
|
|
rotation, useMediaBox, crop, printing, mSliceX, mSliceY, sliceW, sliceH); |
|
|
|
rotation, useMediaBox, crop, printing, sliceX, sliceY, sliceW, sliceH); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mpSplashBitmap = mSplash->getBitmap(); |
|
|
|
SplashBitmap *bitmap = splash.getBitmap(); |
|
|
|
img = new QImage(mpSplashBitmap->getDataPtr(), mpSplashBitmap->getWidth(), mpSplashBitmap->getHeight(), mpSplashBitmap->getWidth() * 3, QImage::Format_RGB888); |
|
|
|
QImage pdfImage(bitmap->getDataPtr(), bitmap->getWidth(), bitmap->getHeight(), bitmap->getWidth() * 3, QImage::Format_RGB888); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QTransform savedTransform = p->worldTransform(); |
|
|
|
|
|
|
|
p->resetTransform(); |
|
|
|
|
|
|
|
p->drawImage(QPointF(savedTransform.dx() + sliceX, savedTransform.dy() + sliceY), pdfImage); |
|
|
|
|
|
|
|
p->setWorldTransform(savedTransform); |
|
|
|
} |
|
|
|
} |
|
|
|
return img; |
|
|
|
|
|
|
|
} |
|
|
|
} |