From 7138cb9c000831244b463ec0de237e7ef9203a76 Mon Sep 17 00:00:00 2001 From: shibakaneki Date: Fri, 24 Jun 2011 14:59:44 +0200 Subject: [PATCH] Resolved bad performance when drawing on top of a PDF --- src/domain/UBGraphicsScene.cpp | 1 + src/pdf/XPDFRenderer.cpp | 103 ++++++++++++++++++++++++--------- src/pdf/XPDFRenderer.h | 20 ++++++- 3 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 31bd2934..318b0449 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "frameworks/UBGeometryUtils.h" #include "frameworks/UBPlatformUtils.h" diff --git a/src/pdf/XPDFRenderer.cpp b/src/pdf/XPDFRenderer.cpp index 893a8d0d..e95acacb 100644 --- a/src/pdf/XPDFRenderer.cpp +++ b/src/pdf/XPDFRenderer.cpp @@ -5,12 +5,6 @@ #include -#include -#include -#include -#include -#include - QAtomicInt XPDFRenderer::sInstancesCount = 0; XPDFRenderer::XPDFRenderer(const QString &filename) @@ -27,7 +21,11 @@ XPDFRenderer::XPDFRenderer(const QString &filename) mDocument = new PDFDoc(new GString(filename.toUtf8().data()), 0, 0, 0); // the filename GString is deleted on PDFDoc desctruction sInstancesCount.ref(); - + bThumbGenerated = false; + bPagesGenerated = false; + mPagesMap.clear(); + mThumbs.clear(); + mThumbMap.clear(); } XPDFRenderer::~XPDFRenderer() @@ -118,47 +116,100 @@ int XPDFRenderer::pageRotation(int pageNumber) const return 0; } - void XPDFRenderer::render(QPainter *p, int pageNumber, const QRectF &bounds) { + if (isValid()) + { + // First verify if the thumbnails and the pages are generated + if(!bThumbGenerated) + { + qreal xscale = p->worldTransform().m11(); + qreal yscale = p->worldTransform().m22(); + 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) + { + qreal xscale = p->worldTransform().m11(); + qreal yscale = p->worldTransform().m22(); + if(!mPagesMap[pageNumber - 1]) + { + // Generate the page + mNumPageToPageMap[pageNumber] = *createPDFImage(pageNumber, xscale, yscale, bounds); + mPagesMap[pageNumber - 1] = true; + if(mPagesMap.size() == mDocument->getNumPages()) + { + bPagesGenerated = true; + } + } + } + + // Warning: verify pagenumber + QImage pdfImage; + + if(!bThumbGenerated) + { + pdfImage = mThumbs.at(pageNumber - 1); + } + else + { + pdfImage = mNumPageToPageMap[pageNumber]; + } + + pdfImage.rect(); + + QTransform savedTransform = p->worldTransform(); + p->resetTransform(); + p->drawImage(QPointF(savedTransform.dx() + mSliceX, savedTransform.dy() + mSliceY), pdfImage); + p->setWorldTransform(savedTransform); + } +} + +QImage* XPDFRenderer::createPDFImage(int pageNumber, const qreal xscale, const qreal yscale, const QRectF &bounds) +{ + QImage* img = new QImage(); if (isValid()) { SplashColor paperColor = {0xFF, 0xFF, 0xFF}; // white - SplashOutputDev splash(splashModeRGB8, 1, gFalse, paperColor); - splash.startDoc(mDocument->getXRef()); + mSplash = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + mSplash->startDoc(mDocument->getXRef()); int hResolution = 72; int vResolution = 72; 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; - const qreal xScale = p->worldTransform().m11(); - const qreal yScale = p->worldTransform().m22(); - qreal sliceX = 0.; - qreal sliceY = 0.; + const qreal xScale = xscale; + const qreal yScale = yscale; + mSliceX = 0.; + mSliceY = 0.; if (bounds.isNull()) { - mDocument->displayPage(&splash, pageNumber, hResolution * xScale, vResolution * yScale, + mDocument->displayPage(mSplash, pageNumber, hResolution * xScale, vResolution * yScale, rotation, useMediaBox, crop, printing); } else { - sliceX = bounds.x() * xScale; - sliceY = bounds.y() * yScale; + mSliceX = bounds.x() * xScale; + mSliceY = bounds.y() * yScale; qreal sliceW = bounds.width() * xScale; qreal sliceH = bounds.height() * yScale; - mDocument->displayPageSlice(&splash, pageNumber, hResolution * xScale, vResolution * yScale, - rotation, useMediaBox, crop, printing, sliceX, sliceY, sliceW, sliceH); + mDocument->displayPageSlice(mSplash, pageNumber, hResolution * xScale, vResolution * yScale, + rotation, useMediaBox, crop, printing, mSliceX, mSliceY, sliceW, sliceH); } - SplashBitmap *bitmap = splash.getBitmap(); - 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); + mpSplashBitmap = mSplash->getBitmap(); + img = new QImage(mpSplashBitmap->getDataPtr(), mpSplashBitmap->getWidth(), mpSplashBitmap->getHeight(), mpSplashBitmap->getWidth() * 3, QImage::Format_RGB888); } + return img; } diff --git a/src/pdf/XPDFRenderer.h b/src/pdf/XPDFRenderer.h index a06d5a04..0782f9fd 100644 --- a/src/pdf/XPDFRenderer.h +++ b/src/pdf/XPDFRenderer.h @@ -1,8 +1,13 @@ #ifndef XPDFRENDERER_H #define XPDFRENDERER_H - +#include #include "PDFRenderer.h" +#include +#include +#include +#include +#include class PDFDoc; @@ -29,10 +34,21 @@ class XPDFRenderer : public PDFRenderer private: void init(); + QImage* createPDFImage(int pageNumber, const qreal xscale = 0.5, const qreal yscale = 0.5, const QRectF &bounds = QRectF()); PDFDoc *mDocument; - + QList mThumbs; + QMap mPagesMap; + QMap mThumbMap; + QMap mNumPageToPageMap; static QAtomicInt sInstancesCount; + qreal mSliceX; + qreal mSliceY; + int bPD; + bool bThumbGenerated; + bool bPagesGenerated; + SplashBitmap* mpSplashBitmap; + SplashOutputDev* mSplash; }; #endif // XPDFRENDERER_H