diff --git a/generators/poppler/generator_pdf.cpp b/generators/poppler/generator_pdf.cpp index 9462195..6080233 100644 --- a/generators/poppler/generator_pdf.cpp +++ b/generators/poppler/generator_pdf.cpp @@ -542,15 +542,43 @@ bool PDFGenerator::init(QVector & pagesVector, const QString &wal return true; } +bool PDFGenerator::lockDocument() const +{ + userMutex()->lock(); +#if POPPLER_QT_THREADSAFE + if (pdfdoc) { + pdfdoc->incRefCnt(); + } + userMutex()->unlock(); +#endif + return pdfdoc != 0; +} + +void PDFGenerator::releaseDocument() +{ +#if POPPLER_QT_THREADSAFE + userMutex()->lock(); + if (pdfdoc) { + if (pdfdoc->decRefCnt()) + pdfdoc = 0; + } +#endif + userMutex()->unlock(); +} + bool PDFGenerator::doCloseDocument() { // remove internal objects userMutex()->lock(); delete annotProxy; annotProxy = 0; +#if POPPLER_QT_THREADSAFE + userMutex()->unlock(); +#else delete pdfdoc; pdfdoc = 0; - userMutex()->unlock(); +#endif + releaseDocument(); docInfoDirty = true; docSynopsisDirty = true; docSyn.clear(); @@ -635,7 +663,7 @@ const Okular::DocumentInfo * PDFGenerator::generateDocumentInfo() { if ( docInfoDirty ) { - userMutex()->lock(); + lockDocument(); docInfo.set( Okular::DocumentInfo::MimeType, "application/pdf" ); @@ -682,7 +710,7 @@ const Okular::DocumentInfo * PDFGenerator::generateDocumentInfo() docInfo.set( Okular::DocumentInfo::Pages, i18n("Unknown") ); } - userMutex()->unlock(); + releaseDocument(); // if pdfdoc is valid then we cached good info -> don't cache them again if ( pdfdoc ) @@ -699,9 +727,11 @@ const Okular::DocumentSynopsis * PDFGenerator::generateDocumentSynopsis() if ( !pdfdoc ) return NULL; - userMutex()->lock(); - QDomDocument *toc = pdfdoc->toc(); - userMutex()->unlock(); + QDomDocument *toc = 0; + if (lockDocument()) { + toc = pdfdoc->toc(); + } + releaseDocument(); if ( !toc ) return NULL; @@ -780,9 +810,10 @@ Okular::FontInfo::List PDFGenerator::fontsForPage( int page ) return list; QList fonts; - userMutex()->lock(); - pdfdoc->scanForFonts( 1, &fonts ); - userMutex()->unlock(); + if (lockDocument()) { + pdfdoc->scanForFonts( 1, &fonts ); + } + releaseDocument(); foreach (const Poppler::FontInfo &font, fonts) { @@ -809,12 +840,20 @@ const QList *PDFGenerator::embeddedFiles() const { if (docEmbeddedFilesDirty) { - userMutex()->lock(); - const QList &popplerFiles = pdfdoc->embeddedFiles(); - foreach(Poppler::EmbeddedFile* pef, popplerFiles) - { + if (lockDocument()) { + const QList &popplerFiles = pdfdoc->embeddedFiles(); + foreach(Poppler::EmbeddedFile* pef, popplerFiles) + { docEmbeddedFiles.append(new PDFEmbeddedFile(pef)); + } } + // can't use releaseDocument because it is not const and modifies pdfdoc +#if POPPLER_QT_THREADSAFE + userMutex()->lock(); + if (pdfdoc) { + pdfdoc->decRefCnt(); + } +#endif userMutex()->unlock(); docEmbeddedFilesDirty = false; @@ -869,11 +908,13 @@ QImage PDFGenerator::image( Okular::PixmapRequest * request ) bool genObjectRects = !rectsGenerated.at( page->number() ); // 0. LOCK [waits for the thread end] - userMutex()->lock(); + Poppler::Page *p = 0; + if (lockDocument()) { // 1. Set OutputDev parameters and Generate contents // note: thread safety is set on 'false' for the GUI (this) thread - Poppler::Page *p = pdfdoc->page(page->number()); + p = pdfdoc->page(page->number()); + } // 2. Take data from outputdev and attach it to the Page QImage img; @@ -899,7 +940,7 @@ QImage PDFGenerator::image( Okular::PixmapRequest * request ) } // 3. UNLOCK [re-enables shared access] - userMutex()->unlock(); + releaseDocument(); delete p; @@ -974,12 +1015,13 @@ Okular::TextPage* PDFGenerator::textPage( Okular::Page *page ) // build a TextList... QList textList; double pageWidth, pageHeight; - Poppler::Page *pp = pdfdoc->page( page->number() ); + Poppler::Page *pp = 0; + if (lockDocument()) { + pp= pdfdoc->page( page->number() ); + } if (pp) { - userMutex()->lock(); textList = pp->textList(); - userMutex()->unlock(); QSizeF s = pp->pageSizeF(); pageWidth = s.width(); @@ -992,7 +1034,7 @@ Okular::TextPage* PDFGenerator::textPage( Okular::Page *page ) pageWidth = defaultPageWidth; pageHeight = defaultPageHeight; } - + releaseDocument(); Okular::TextPage *tp = abstractTextPage(textList, pageHeight, pageWidth, (Poppler::Page::Rotation)page->orientation()); qDeleteAll(textList); return tp; @@ -1001,7 +1043,13 @@ Okular::TextPage* PDFGenerator::textPage( Okular::Page *page ) void PDFGenerator::requestFontData(const Okular::FontInfo &font, QByteArray *data) { Poppler::FontInfo fi = font.nativeId().value(); - *data = pdfdoc->fontData(fi); + if (lockDocument()) { + *data = pdfdoc->fontData(fi); + } else { + QByteArray result; + *data = result; + } + releaseDocument(); } #define DUMMY_QPRINTER_COPY @@ -1020,15 +1068,17 @@ bool PDFGenerator::print( QPrinter& printer ) printer.newPage(); const int page = pageList.at( i ) - 1; - userMutex()->lock(); - Poppler::Page *pp = pdfdoc->page( page ); + Poppler::Page *pp = 0; + if (lockDocument()) { + pp = pdfdoc->page( page ); + } if (pp) { QImage img = pp->renderToImage( printer.physicalDpiX(), printer.physicalDpiY() ); painter.drawImage( painter.window(), img, QRectF(0, 0, img.width(), img.height()) ); delete pp; } - userMutex()->unlock(); + releaseDocument(); } painter.end(); return true; @@ -1100,10 +1150,9 @@ bool PDFGenerator::print( QPrinter& printer ) psConverter->setPSOptions(psConverter->psOptions() | Poppler::PSConverter::HideAnnotations ); #endif - userMutex()->lock(); - if (psConverter->convert()) + if (lockDocument() && psConverter->convert()) { - userMutex()->unlock(); + releaseDocument(); delete psConverter; tf.close(); int ret = Okular::FilePrinter::printFile( printer, tempfilename, @@ -1120,7 +1169,7 @@ bool PDFGenerator::print( QPrinter& printer ) { lastPrintError = FileConversionPrintError; delete psConverter; - userMutex()->unlock(); + releaseDocument(); } tf.close(); @@ -1153,8 +1202,17 @@ QVariant PDFGenerator::metaData( const QString & key, const QVariant & option ) { // asking for the page related to a 'named link destination'. the // option is the link name. @see addSynopsisChildren. + Poppler::LinkDestination *ld = 0; + if (lockDocument()) { + ld = pdfdoc->linkDestination( optionString ); + } + // can't use releaseDocument because it is not const and modifies pdfdoc +#if POPPLER_QT_THREADSAFE userMutex()->lock(); - Poppler::LinkDestination *ld = pdfdoc->linkDestination( optionString ); + if (pdfdoc) { + pdfdoc->decRefCnt(); + } +#endif userMutex()->unlock(); if ( ld ) { @@ -1167,8 +1225,17 @@ QVariant PDFGenerator::metaData( const QString & key, const QVariant & option ) } else if ( key == "DocumentTitle" ) { + QString title; + if (lockDocument()) { + title = pdfdoc->info( "Title" ); + } + // can't use releaseDocument because it is not const and modifies pdfdoc +#if POPPLER_QT_THREADSAFE userMutex()->lock(); - QString title = pdfdoc->info( "Title" ); + if (pdfdoc) { + pdfdoc->decRefCnt(); + } +#endif userMutex()->unlock(); return title; } @@ -1199,9 +1266,7 @@ bool PDFGenerator::reparseConfig() // over the page rendered on 'standard' white background. if ( color != pdfdoc->paperColor() ) { - userMutex()->lock(); pdfdoc->setPaperColor(color); - userMutex()->unlock(); somethingchanged = true; } bool aaChanged = setDocumentRenderHints(); @@ -1257,13 +1322,15 @@ bool PDFGenerator::exportTo( const QString &fileName, const Okular::ExportFormat for ( int i = 0; i < num; ++i ) { QString text; - userMutex()->lock(); - Poppler::Page *pp = pdfdoc->page(i); + Poppler::Page *pp = 0; + if (lockDocument()) { + pp = pdfdoc->page(i); + } if (pp) { text = pp->text(QRect()).normalized(QString::NormalizationForm_KC); } - userMutex()->unlock(); + releaseDocument(); ts << text; delete pp; } diff --git a/generators/poppler/generator_pdf.h b/generators/poppler/generator_pdf.h index bea65d9..6d5f1e9 100644 --- a/generators/poppler/generator_pdf.h +++ b/generators/poppler/generator_pdf.h @@ -124,6 +124,10 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p void initSynctexParser( const QString& filePath ); // search document for source reference void fillViewportFromSourceReference( Okular::DocumentViewport & viewport, const QString & reference ) const; + // protect document against deletion + bool lockDocument() const; + // release document + void releaseDocument(); Okular::TextPage * abstractTextPage(const QList &text, double height, double width, int rot);