⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generator_pdf.cpp.svn-base

📁 okular
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/*************************************************************************** *   Copyright (C) 2004-2006 by Albert Astals Cid <tsdgeos@terra.es>       * *   Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>                  * *                                                                         * *   This program 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; either version 2 of the License, or     * *   (at your option) any later version.                                   * ***************************************************************************/// qt/kde includes#include <qfile.h>#include <qimage.h>#include <qregexp.h>#include <qtextstream.h>#include <kauthorized.h>#include <klocale.h>#include <kpassworddialog.h>#include <kwallet.h>#include <kprinter.h>#include <ktempfile.h>#include <kmessagebox.h>#include <kdebug.h>// local includes#include "generator_pdf.h"#include "core/observer.h" //for PAGEVIEW_ID#include "core/page.h"#include "core/annotations.h"#include "core/pagetransition.h"#include "settings.h"#include <config.h>#include <config-okular.h>class PDFEmbeddedFile : public EmbeddedFile{    public:        PDFEmbeddedFile(Poppler::EmbeddedFile *f) : ef(f)        {        }                QString name() const        {            return ef->name();        }                QString description() const        {            return ef->description();        }                QByteArray data() const        {            return ef->data();        }                QDateTime modificationDate() const        {            return ef->modDate();        }                QDateTime creationDate() const        {            return ef->createDate();        }        private:        Poppler::EmbeddedFile *ef;};static void fillViewportFromLinkDestination( DocumentViewport &viewport, const Poppler::LinkDestination &destination, const Poppler::Document *pdfdoc ){    viewport.pageNumber = destination.pageNumber() - 1;    if (viewport.pageNumber == -1) return;    // get destination position    // TODO add other attributes to the viewport (taken from link)//     switch ( destination->getKind() )//     {//         case destXYZ:            if (destination.isChangeLeft() || destination.isChangeTop())            {                Poppler::Page *page = pdfdoc->page( viewport.pageNumber );                // TODO remember to change this if we implement DPI and/or rotation                double left, top;                left = destination.left();                top = destination.top();                QSize pageSize = page->pageSize();                delete page;                viewport.rePos.normalizedX = (double)left / (double)pageSize.width();                viewport.rePos.normalizedY = (double)top / (double)pageSize.height();                viewport.rePos.enabled = true;                viewport.rePos.pos = DocumentViewport::TopLeft;            }            /* TODO            if ( dest->getChangeZoom() )                make zoom change*//*        break;        default:            // implement the others cases        break;*///     }}static KPDFLink* createKPDFLinkFromPopplerLink(const Poppler::Link *popplerLink, const Poppler::Document *pdfdoc){	KPDFLink *kpdfLink = 0;	const Poppler::LinkGoto *popplerLinkGoto;	const Poppler::LinkExecute *popplerLinkExecute;	const Poppler::LinkBrowse *popplerLinkBrowse;	const Poppler::LinkAction *popplerLinkAction;	DocumentViewport viewport;		switch(popplerLink->linkType())	{		case Poppler::Link::None:		break;			case Poppler::Link::Goto:			popplerLinkGoto = static_cast<const Poppler::LinkGoto *>(popplerLink);			fillViewportFromLinkDestination( viewport, popplerLinkGoto->destination(), pdfdoc );			kpdfLink = new KPDFLinkGoto(popplerLinkGoto->fileName(), viewport);		break;				case Poppler::Link::Execute:			popplerLinkExecute = static_cast<const Poppler::LinkExecute *>(popplerLink);			kpdfLink = new KPDFLinkExecute( popplerLinkExecute->fileName(), popplerLinkExecute->parameters() );		break;				case Poppler::Link::Browse:			popplerLinkBrowse = static_cast<const Poppler::LinkBrowse *>(popplerLink);			kpdfLink = new KPDFLinkBrowse( popplerLinkBrowse->url() );		break;				case Poppler::Link::Action:			popplerLinkAction = static_cast<const Poppler::LinkAction *>(popplerLink);			kpdfLink = new KPDFLinkAction( (KPDFLinkAction::ActionType)popplerLinkAction->actionType() );		break;				case Poppler::Link::Movie:			// not implemented		break;	}		return kpdfLink;}static QLinkedList<ObjectRect*> generateKPDFLinks( const QList<Poppler::Link*> &popplerLinks, int width, int height, const Poppler::Document *pdfdoc ){	QLinkedList<ObjectRect*> kpdfLinks;	foreach(const Poppler::Link *popplerLink, popplerLinks)	{		QRectF linkArea = popplerLink->linkArea();		double nl = linkArea.left() / (double)width,		       nt = linkArea.top() / (double)height,		       nr = linkArea.right() / (double)width,		       nb = linkArea.bottom() / (double)height;		// create the rect using normalized coords and attach the KPDFLink to it		ObjectRect * rect = new ObjectRect( nl, nt, nr, nb, false, ObjectRect::Link, createKPDFLinkFromPopplerLink(popplerLink, pdfdoc) );		// add the ObjectRect to the container		kpdfLinks.push_front( rect );	}	qDeleteAll(popplerLinks);	return kpdfLinks;}/** NOTES on threading: * internal: thread race prevention is done via the 'docLock' mutex. the *           mutex is needed only because we have the asynchronous thread; else *           the operations are all within the 'gui' thread, scheduled by the *           Qt scheduler and no mutex is needed. * external: dangerous operations are all locked via mutex internally, and the *           only needed external thing is the 'canGeneratePixmap' method *           that tells if the generator is free (since we don't want an *           internal queue to store PixmapRequests). A generatedPixmap call *           without the 'ready' flag set, results in undefined behavior. * So, as example, printing while generating a pixmap asynchronously is safe, * it might only block the gui thread by 1) waiting for the mutex to unlock * in async thread and 2) doing the 'heavy' print operation. */OKULAR_EXPORT_PLUGIN(PDFGenerator)PDFGenerator::PDFGenerator( KPDFDocument * doc )    : Generator( doc ), pdfdoc( 0 ), ready( true ),    pixmapRequest( 0 ), docInfoDirty( true ), docSynopsisDirty( true ),    docFontsDirty( true ), docEmbeddedFilesDirty( true ){    // update the configuration    reparseConfig();    // generate the pixmapGeneratorThread    generatorThread = new PDFPixmapGeneratorThread( this );    connect(generatorThread, SIGNAL(finished()), this, SLOT(threadFinished()), Qt::QueuedConnection);}PDFGenerator::~PDFGenerator(){    // stop and delete the generator thread    if ( generatorThread )    {        generatorThread->wait();        delete generatorThread;    }}void PDFGenerator::setOrientation(QVector<KPDFPage*> & pagesVector, int orientation){    loadPages(pagesVector,orientation,true);}//BEGIN Generator inherited functionsbool PDFGenerator::loadDocument( const QString & filePath, QVector<KPDFPage*> & pagesVector ){#ifndef NDEBUG    if ( pdfdoc )    {        kDebug() << "PDFGenerator: multiple calls to loadDocument. Check it." << endl;        return false;    }#endif    // create PDFDoc for the given file    pdfdoc = Poppler::Document::load( filePath, 0, 0 );    // if the file didn't open correctly it might be encrypted, so ask for a pass    bool firstInput = true;    bool triedWallet = false;    KWallet::Wallet * wallet = 0;    while ( !pdfdoc && pdfdoc->isLocked() )    {        QByteArray password;        // 1.A. try to retrieve the first password from the kde wallet system        if ( !triedWallet )        {            QString walletName = KWallet::Wallet::NetworkWallet();            wallet = KWallet::Wallet::openWallet( walletName );            if ( wallet )            {                // use the KPdf folder (and create if missing)                if ( !wallet->hasFolder( "KPdf" ) )                    wallet->createFolder( "KPdf" );                wallet->setFolder( "KPdf" );                // look for the pass in that folder                QString retrievedPass;                if ( !wallet->readPassword( filePath.section('/', -1, -1), retrievedPass ) )                    password = retrievedPass.toLocal8Bit();            }            triedWallet = true;        }        // 1.B. if not retrieved, ask the password using the kde password dialog        if ( password.isNull() )        {            QString prompt;            if ( firstInput )                prompt = i18n( "Please insert the password to read the document:" );            else                prompt = i18n( "Incorrect password. Try again:" );            firstInput = false;            // if the user presses cancel, abort opening            if ( KPasswordDialog::getPassword( 0, password, prompt ) != KPasswordDialog::Accepted )                break;        }        // 2. reopen the document using the password        pdfdoc->unlock( password, password );        // 3. if the password is correct, store it to the wallet        if ( !pdfdoc->isLocked() && wallet && /*safety check*/ wallet->isOpen() )        {            QString goodPass = QString::fromLocal8Bit( password.data() );            wallet->writePassword( filePath.section('/', -1, -1), goodPass );        }    }    if ( !pdfdoc )    {        pdfdoc = 0;        return false;    }    // build Pages (currentPage was set -1 by deletePages)    uint pageCount = pdfdoc->numPages();    pagesVector.resize(pageCount);    loadPages(pagesVector, 0, false);    // the file has been loaded correctly    return true;}bool PDFGenerator::closeDocument(){    // remove internal objects    docLock.lock();    delete pdfdoc;    pdfdoc = 0;    docLock.unlock();    return true;}void PDFGenerator::loadPages(QVector<KPDFPage*> &pagesVector, int rotation, bool clear){    // TODO XPDF 3.01 check    int count=pagesVector.count(),w=0,h=0;    for ( int i = 0; i < count ; i++ )    {        // get xpdf page        Poppler::Page * p = pdfdoc->page( i );        QSize pSize = p->pageSize();        w = pSize.width();        h = pSize.height();        int orientation;        switch (p->orientation())        {          case Poppler::Page::Landscape: orientation = 1; break;          case Poppler::Page::UpsideDown: orientation = 2; break;          case Poppler::Page::Seascape: orientation = 3; break;          case Poppler::Page::Portrait: orientation = 0; break;        }        if (rotation % 2 == 1)          qSwap(w,h);        // init a kpdfpage, add transition and annotation information        KPDFPage * page = new KPDFPage( i, w, h, orientation );        addTransition( p, page );        if ( true ) //TODO real check          addAnnotations( p, page );// 	    kWarning() << page->width() << "x" << page->height() << endl;// need a way to find efficient (maybe background textpage generation)	kDebug() << "loadpages with rotation" << rotation << " and orientation " << orientation << endl;	docLock.lock();	QList<Poppler::TextBox*> textList = p->textList((Poppler::Page::Rotation)rotation);	docLock.unlock();	page->setSearchPage(abstractTextPage(textList, page->height(), page->width(), orientation));		qDeleteAll(textList);	delete p;        if (clear && pagesVector[i])            delete pagesVector[i];        // set the kpdfpage at the right position in document's pages vector        pagesVector[i] = page;// 	kWarning() << page->width() << "x" << page->height() << endl;    }}QString PDFGenerator::getText( const RegularAreaRect * area, KPDFPage * page  ){    QRect rect = area->first()->geometry((int)page->width(),(int)page->height());    Poppler::Page *pp = pdfdoc->page( page->number() );    QString text = pp->text(rect);    delete pp;    return text;}RegularAreaRect * PDFGenerator::findText (const QString & text, SearchDir dir,     const bool strictCase, const RegularAreaRect * sRect, KPDFPage * page ){    dir = sRect ? NextRes : FromTop;    QRectF rect;    if ( dir == NextRes )    {        // when using thein ternal search we only play with normrects        rect.setLeft( sRect->first()->left * page->width() );        rect.setTop( sRect->first()->top * page->height() );        rect.setRight( sRect->first()->right * page->width() );        rect.setBottom( sRect->first()->bottom * page->height() );    }    // this loop is only for 'bad case' Reses    bool found = false;    Poppler::Page *pp = pdfdoc->page( page->number() );    docLock.lock();    Poppler::Page::SearchMode sm;    if (strictCase) sm = Poppler::Page::CaseSensitive;    else sm = Poppler::Page::CaseInsensitive;    while ( !found )    {        if ( dir == FromTop ) found = pp->search(text, rect, Poppler::Page::FromTop, sm);        else if ( dir == NextRes ) found = pp->search(text, rect, Poppler::Page::NextResult, sm);        else if ( dir == PrevRes ) found = pp->search(text, rect, Poppler::Page::PreviousResult, sm);        // if not found (even in case unsensitive search), terminate        if ( !found )            break;    }    docLock.unlock();    delete pp;    // if the page was found, return a new normalizedRect    if ( found )    {        RegularAreaRect *ret=new RegularAreaRect;        ret->append (new NormalizedRect( rect.left() / page->width(), rect.top() / page->height(),             rect.right() / page->width(), rect.bottom() / page->height() ) );        return ret;    }    return 0;}const DocumentInfo * PDFGenerator::generateDocumentInfo(){    if ( docInfoDirty )    {        docLock.lock();                docInfo.set( "mimeType", "application/pdf" );                if ( pdfdoc )        {            // compile internal structure reading properties from PDFDoc            docInfo.set( "title", pdfdoc->info("Title"), i18n("Title") );            docInfo.set( "subject", pdfdoc->info("Subject"), i18n("Subject") );            docInfo.set( "author", pdfdoc->info("Author"), i18n("Author") );            docInfo.set( "keywords", pdfdoc->info("Keywords"), i18n("Keywords") );            docInfo.set( "creator", pdfdoc->info("Creator"), i18n("Creator") );            docInfo.set( "producer", pdfdoc->info("Producer"), i18n("Producer") );            docInfo.set( "creationDate", KGlobal::locale()->formatDateTime( pdfdoc->date("CreationDate"), false, true ), i18n("Created") );            docInfo.set( "modificationDate", KGlobal::locale()->formatDateTime( pdfdoc->date("ModDate"), false, true ), i18n("Modified") );            docInfo.set( "format", i18nc( "PDF v. <version>", "PDF v. %1",                         QString::number( pdfdoc->pdfVersion() ) ), i18n( "Format" ) );            docInfo.set( "encryption", pdfdoc->isEncrypted() ? i18n( "Encrypted" ) : i18n( "Unencrypted" ),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -