You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.7 KiB
203 lines
5.7 KiB
/* |
|
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) |
|
* |
|
* Copyright (C) 2013 Open Education Foundation |
|
* |
|
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour |
|
* l'Education Numérique en Afrique (GIP ENA) |
|
* |
|
* This file is part of OpenBoard. |
|
* |
|
* OpenBoard is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, version 3 of the License, |
|
* with a specific linking exception for the OpenSSL project's |
|
* "OpenSSL" library (or with modified versions of it that use the |
|
* same license as the "OpenSSL" library). |
|
* |
|
* OpenBoard is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with OpenBoard. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
|
|
|
|
|
|
#include "XPDFRenderer.h" |
|
|
|
#include <QtGui> |
|
|
|
#include <frameworks/UBPlatformUtils.h> |
|
|
|
#include "core/memcheck.h" |
|
|
|
QAtomicInt XPDFRenderer::sInstancesCount = 0; |
|
|
|
XPDFRenderer::XPDFRenderer(const QString &filename, bool importingFile) |
|
: mDocument(0) |
|
, mpSplashBitmap(0) |
|
, mSplash(0) |
|
{ |
|
Q_UNUSED(importingFile); |
|
if (!globalParams) |
|
{ |
|
// globalParams must be allocated once and never be deleted |
|
// note that this is *not* an instance variable of this XPDFRenderer class |
|
globalParams = new GlobalParams(0); |
|
globalParams->setupBaseFonts(QFile::encodeName(UBPlatformUtils::applicationResourcesDirectory() + "/" + "fonts").data()); |
|
} |
|
|
|
mDocument = new PDFDoc(new GString(filename.toLocal8Bit()), 0, 0, 0); // the filename GString is deleted on PDFDoc desctruction |
|
sInstancesCount.ref(); |
|
} |
|
|
|
XPDFRenderer::~XPDFRenderer() |
|
{ |
|
if(mSplash){ |
|
delete mSplash; |
|
mSplash = NULL; |
|
} |
|
|
|
if (mDocument) |
|
{ |
|
delete mDocument; |
|
sInstancesCount.deref(); |
|
} |
|
|
|
if (sInstancesCount.loadAcquire() == 0 && globalParams) |
|
{ |
|
delete globalParams; |
|
globalParams = 0; |
|
} |
|
} |
|
|
|
bool XPDFRenderer::isValid() const |
|
{ |
|
if (mDocument) |
|
{ |
|
return mDocument->isOk(); |
|
} |
|
else |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
int XPDFRenderer::pageCount() const |
|
{ |
|
if (isValid()) |
|
return mDocument->getNumPages(); |
|
else |
|
return 0; |
|
} |
|
|
|
QString XPDFRenderer::title() const |
|
{ |
|
if (isValid()) |
|
{ |
|
Object pdfInfo; |
|
mDocument->getDocInfo(&pdfInfo); |
|
if (pdfInfo.isDict()) |
|
{ |
|
Object title; |
|
Dict *infoDict = pdfInfo.getDict(); |
|
if (infoDict->lookup((char*)"Title", &title)->isString()) |
|
{ |
|
GString *gstring = title.getString(); |
|
return QString(gstring->getCString()); |
|
} |
|
} |
|
} |
|
|
|
return QString(); |
|
} |
|
|
|
|
|
QSizeF XPDFRenderer::pageSizeF(int pageNumber) const |
|
{ |
|
qreal cropWidth = 0; |
|
qreal cropHeight = 0; |
|
|
|
if (isValid()) |
|
{ |
|
int rotate = mDocument->getPageRotate(pageNumber); |
|
|
|
cropWidth = mDocument->getPageCropWidth(pageNumber) * this->dpiForRendering / 72.0; |
|
cropHeight = mDocument->getPageCropHeight(pageNumber) * this->dpiForRendering / 72.0; |
|
|
|
if (rotate == 90 || rotate == 270) |
|
{ |
|
//switching width and height |
|
qreal tmpVar = cropWidth; |
|
cropWidth = cropHeight; |
|
cropHeight = tmpVar; |
|
} |
|
} |
|
return QSizeF(cropWidth, cropHeight); |
|
} |
|
|
|
|
|
int XPDFRenderer::pageRotation(int pageNumber) const |
|
{ |
|
if (mDocument) |
|
return mDocument->getPageRotate(pageNumber); |
|
else |
|
return 0; |
|
} |
|
|
|
void XPDFRenderer::render(QPainter *p, int pageNumber, const QRectF &bounds) |
|
{ |
|
if (isValid()) |
|
{ |
|
qreal xscale = p->worldTransform().m11(); |
|
qreal yscale = p->worldTransform().m22(); |
|
|
|
QImage *pdfImage = createPDFImage(pageNumber, xscale, yscale, bounds); |
|
QTransform savedTransform = p->worldTransform(); |
|
p->resetTransform(); |
|
p->drawImage(QPointF(savedTransform.dx() + mSliceX, savedTransform.dy() + mSliceY), *pdfImage); |
|
p->setWorldTransform(savedTransform); |
|
delete pdfImage; |
|
} |
|
} |
|
|
|
QImage* XPDFRenderer::createPDFImage(int pageNumber, qreal xscale, qreal yscale, const QRectF &bounds) |
|
{ |
|
if (isValid()) |
|
{ |
|
SplashColor paperColor = {0xFF, 0xFF, 0xFF}; // white |
|
if(mSplash) |
|
delete mSplash; |
|
mSplash = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); |
|
mSplash->startDoc(mDocument->getXRef()); |
|
int rotation = 0; // in degrees (get it from the worldTransform if we want to support rotation) |
|
GBool useMediaBox = gFalse; |
|
GBool crop = gTrue; |
|
GBool printing = gFalse; |
|
mSliceX = 0.; |
|
mSliceY = 0.; |
|
|
|
if (bounds.isNull()) |
|
{ |
|
mDocument->displayPage(mSplash, pageNumber, this->dpiForRendering * xscale, this->dpiForRendering *yscale, |
|
rotation, useMediaBox, crop, printing); |
|
} |
|
else |
|
{ |
|
mSliceX = bounds.x() * xscale; |
|
mSliceY = bounds.y() * yscale; |
|
qreal sliceW = bounds.width() * xscale; |
|
qreal sliceH = bounds.height() * yscale; |
|
|
|
mDocument->displayPageSlice(mSplash, pageNumber, this->dpiForRendering * xscale, this->dpiForRendering * yscale, |
|
rotation, useMediaBox, crop, printing, mSliceX, mSliceY, sliceW, sliceH); |
|
} |
|
|
|
mpSplashBitmap = mSplash->getBitmap(); |
|
} |
|
return new QImage(mpSplashBitmap->getDataPtr(), mpSplashBitmap->getWidth(), mpSplashBitmap->getHeight(), mpSplashBitmap->getWidth() * 3, QImage::Format_RGB888); |
|
}
|
|
|