📄 generator_pdf.cpp
字号:
wordRect->right/width, word->edge(j)/height); } if ( word->hasSpaceAfter() && next ) append(ktp, " ", // this letters boundary wordRect->left/width, next->edge(0)/height, // next letters boundary wordRect->right/width, word->edge(charCount)/height); break; } } delete wordRect; return ktp;}void PDFGenerator::addSynopsisChildren( QDomNode * parent, QDomNode * parentDestination ){ // keep track of the current listViewItem QDomNode n = parent->firstChild(); while( !n.isNull() ) { // convert the node to an element (sure it is) QDomElement e = n.toElement(); // The name is the same QDomElement item = docSyn.createElement( e.tagName() ); parentDestination->appendChild(item); if (!e.attribute("ExternalFileName").isNull()) item.setAttribute("ExternalFileName", e.attribute("ExternalFileName")); if (!e.attribute("DestinationName").isNull()) item.setAttribute("ViewportName", e.attribute("DestinationName")); if (!e.attribute("Destination").isNull()) { DocumentViewport vp; fillViewportFromLinkDestination( vp, Poppler::LinkDestination(e.attribute("Destination")), pdfdoc ); item.setAttribute( "Viewport", vp.toString() ); } // descend recursively and advance to the next node if ( e.hasChildNodes() ) addSynopsisChildren( &n, & item ); n = n.nextSibling(); }}void PDFGenerator::addAnnotations( Poppler::Page * popplerPage, KPDFPage * page ){ QList<Poppler::Annotation*> popplerAnnotations = popplerPage->annotations(); foreach(Poppler::Annotation *a, popplerAnnotations) { Annotation* ann=getokularAnnot(a); page->addAnnotation( ann ); //a->window.width = (int)(page->width() * a->window.width); //a->window.height = (int)(page->height() * a->window.height); //a->window.width = a->window.width < 200 ? 200 : a->window.width; // a->window.height = a->window.height < 120 ? 120 : a->window.height; // resize annotation's geometry to an icon // TODO okular geom.right = geom.left + 22.0 / page->width(); // TODO okular geom.bottom = geom.top + 22.0 / page->height(); QString szanno; QTextStream(&szanno)<<"PopplerAnnotation={subType:"<<a->subType() <<", author:"<<a->author <<", contents:"<<a->contents <<", uniqueName:"<<a->uniqueName <<", modifyDate:"<<a->modifyDate.toString("hh:mm:ss, dd.MM.yyyy") <<", creationDate:"<<a->creationDate.toString("hh:mm:ss, dd.MM.yyyy") <<", flags:"<<a->flags <<", boundary:"<<a->boundary.left()<<","<<a->boundary.top()<<","<<a->boundary.right()<<","<<a->boundary.bottom() <<", style.color:"<<a->style.color.name() <<", style.opacity:"<<a->style.opacity <<", style.width:"<<a->style.width <<", style.LineStyle:"<<a->style.style <<", style.xyCorners:"<<a->style.xCorners<<","<<a->style.yCorners <<", style.marks:"<<a->style.marks <<", style.spaces:"<<a->style.spaces <<", style.LineEffect:"<<a->style.effect <<", style.effectIntensity:"<<a->style.effectIntensity <<", window.flags:"<<a->window.flags <<", window.topLeft:"<<(a->window.topLeft.x()) <<","<<(a->window.topLeft.y()) <<", window.width,height:"<<a->window.width<<","<<a->window.height <<", window.title:"<<a->window.title <<", window.summary:"<<a->window.summary <<", window.text:"<<a->window.text; kDebug( )<<"astario: "<<szanno<<endl; // this is uber ugly but i don't know a better way to do it without introducing a poppler::annotation dependency on core //TODO add annotations after poppler write feather is full suported /*QDomDocument doc; QDomElement root = doc.createElement("root"); doc.appendChild(root); a->store( root, doc );*/ } qDeleteAll(popplerAnnotations);}void PDFGenerator::addTransition( Poppler::Page * pdfPage, KPDFPage * page )// called on opening when MUTEX is not used{ Poppler::PageTransition *pdfTransition = pdfPage->transition(); if ( !pdfTransition || pdfTransition->type() == Poppler::PageTransition::Replace ) return; KPDFPageTransition *transition = new KPDFPageTransition(); switch ( pdfTransition->type() ) { case Poppler::PageTransition::Replace: // won't get here, added to avoid warning break; case Poppler::PageTransition::Split: transition->setType( KPDFPageTransition::Split ); break; case Poppler::PageTransition::Blinds: transition->setType( KPDFPageTransition::Blinds ); break; case Poppler::PageTransition::Box: transition->setType( KPDFPageTransition::Box ); break; case Poppler::PageTransition::Wipe: transition->setType( KPDFPageTransition::Wipe ); break; case Poppler::PageTransition::Dissolve: transition->setType( KPDFPageTransition::Dissolve ); break; case Poppler::PageTransition::Glitter: transition->setType( KPDFPageTransition::Glitter ); break; case Poppler::PageTransition::Fly: transition->setType( KPDFPageTransition::Fly ); break; case Poppler::PageTransition::Push: transition->setType( KPDFPageTransition::Push ); break; case Poppler::PageTransition::Cover: transition->setType( KPDFPageTransition::Cover ); break; case Poppler::PageTransition::Uncover: transition->setType( KPDFPageTransition::Uncover ); break; case Poppler::PageTransition::Fade: transition->setType( KPDFPageTransition::Fade ); break; } transition->setDuration( pdfTransition->duration() ); switch ( pdfTransition->alignment() ) { case Poppler::PageTransition::Horizontal: transition->setAlignment( KPDFPageTransition::Horizontal ); break; case Poppler::PageTransition::Vertical: transition->setAlignment( KPDFPageTransition::Vertical ); break; } switch ( pdfTransition->direction() ) { case Poppler::PageTransition::Inward: transition->setDirection( KPDFPageTransition::Inward ); break; case Poppler::PageTransition::Outward: transition->setDirection( KPDFPageTransition::Outward ); break; } transition->setAngle( pdfTransition->angle() ); transition->setScale( pdfTransition->scale() ); transition->setIsRectangular( pdfTransition->isRectangular() ); page->setTransition( transition );}void PDFGenerator::threadFinished(){#if 0 // check if thread is running (has to be stopped now) if ( generatorThread->running() ) { // if so, wait for effective thread termination if ( !generatorThread->wait( 9999 /*10s timeout*/ ) ) { kWarning() << "PDFGenerator: thread sent 'data available' " << "signal but had problems ending." << endl; return; }}#endif // 1. the mutex must be unlocked now bool isLocked = true; if (docLock.tryLock()) { docLock.unlock(); isLocked = false; } if ( isLocked ) { kWarning() << "PDFGenerator: 'data available' but mutex still " << "held. Recovering." << endl; // synchronize GUI thread (must not happen) docLock.lock(); docLock.unlock(); } // 2. put thread's generated data into the KPDFPage PixmapRequest * request = generatorThread->request(); QImage * outImage = generatorThread->takeImage(); QList<Poppler::TextBox*> outText = generatorThread->takeText(); QLinkedList< ObjectRect * > outRects = generatorThread->takeObjectRects(); QPixmap * newpix = new QPixmap(); *newpix = QPixmap::fromImage( *outImage ); request->page->setPixmap( request->id, newpix ); delete outImage; if ( !outText.isEmpty() ) { request->page->setSearchPage( abstractTextPage( outText , request->page->height(), request->page->width(),request->page->orientation())); qDeleteAll(outText); } bool genObjectRects = request->id & (PAGEVIEW_ID | PRESENTATION_ID); if (genObjectRects) request->page->setObjectRects( outRects ); // 3. tell generator that data has been taken generatorThread->endGeneration(); // update ready state ready = true; // notify the new generation signalRequestDone( request );}/** The PDF Pixmap Generator Thread **/struct PPGThreadPrivate{ // reference to main objects PDFGenerator * generator; PixmapRequest * currentRequest; // internal temp stored items. don't delete this. QImage * m_image; QList<Poppler::TextBox*> m_textList; QLinkedList< ObjectRect * > m_rects; bool m_rectsTaken;};PDFPixmapGeneratorThread::PDFPixmapGeneratorThread( PDFGenerator * gen ) : QThread(), d( new PPGThreadPrivate() ){ d->generator = gen; d->currentRequest = 0; d->m_image = 0; d->m_rectsTaken = true;}PDFPixmapGeneratorThread::~PDFPixmapGeneratorThread(){ // delete internal objects if the class is deleted before the gui thread // takes the data delete d->m_image; qDeleteAll(d->m_textList); if ( !d->m_rectsTaken && d->m_rects.count() ) { qDeleteAll(d->m_rects); } delete d->currentRequest; // delete internal storage structure delete d;}void PDFPixmapGeneratorThread::startGeneration( PixmapRequest * request ){#ifndef NDEBUG // check if a generation is already running if ( d->currentRequest ) { kDebug() << "PDFPixmapGeneratorThread: requesting a pixmap " << "when another is being generated." << endl; delete request; return; } // check if the mutex is already held bool isLocked = true; if (d->generator->docLock.tryLock()) { d->generator->docLock.unlock(); isLocked = false; } if ( isLocked ) { kDebug() << "PDFPixmapGeneratorThread: requesting a pixmap " << "with the mutex already held." << endl; delete request; return; }#endif // set generation parameters and run thread d->currentRequest = request; start( QThread::InheritPriority );}void PDFPixmapGeneratorThread::endGeneration(){#ifndef NDEBUG // check if a generation is already running if ( !d->currentRequest ) { kDebug() << "PDFPixmapGeneratorThread: 'end generation' called " << "but generation was not started." << endl; return; }#endif // reset internal members preparing for a new generation d->currentRequest = 0;}PixmapRequest *PDFPixmapGeneratorThread::request() const{ return d->currentRequest;}QImage * PDFPixmapGeneratorThread::takeImage() const{ QImage * img = d->m_image; d->m_image = 0; return img;}QList<Poppler::TextBox*> PDFPixmapGeneratorThread::takeText(){ QList<Poppler::TextBox*> tl = d->m_textList; d->m_textList.clear(); return tl;}QLinkedList< ObjectRect * > PDFPixmapGeneratorThread::takeObjectRects() const{ d->m_rectsTaken = true; return d->m_rects;}void PDFPixmapGeneratorThread::run()// perform contents generation, when the MUTEX is already LOCKED// @see PDFGenerator::generatePixmap( .. ) (and be aware to sync the code){ // compute dpi used to get an image with desired width and height KPDFPage * page = d->currentRequest->page; int width = d->currentRequest->width, height = d->currentRequest->height; double fakeDpiX = width * 72.0 / page->width(), fakeDpiY = height * 72.0 / page->height(); // setup kpdf output device: text page is generated only if we are at 72dpi. // since we can pre-generate the TextPage at the right res.. why not? bool genTextPage = !page->hasSearchPage() && ( width == page->width() ) && ( height == page->height() ); // generate links and image rects if rendering pages on pageview bool genObjectRects = d->currentRequest->id & (PAGEVIEW_ID | PRESENTATION_ID); // 0. LOCK s[tart locking XPDF thread unsafe classes] d->generator->docLock.lock(); // 1. set OutputDev parameters and Generate contents Poppler::Page *pp = d->generator->pdfdoc->page( page->number() ); // 2. grab data from the OutputDev and store it locally (note takeIMAGE)#ifndef NDEBUG if ( d->m_image ) kDebug() << "PDFPixmapGeneratorThread: previous image not taken" << endl; if ( !d->m_textList.isEmpty() ) kDebug() << "PDFPixmapGeneratorThread: previous text not taken" << endl;#endif d->m_image = new QImage( pp->splashRenderToImage( fakeDpiX, fakeDpiY, -1, -1, -1, -1, genObjectRects, (Poppler::Page::Rotation)d->currentRequest->documentRotation ) ); if ( genObjectRects ) { d->m_rects = generateKPDFLinks(pp->links(), width, height, d->generator->pdfdoc); } else d->m_rectsTaken = false; if ( genTextPage ) { d->m_textList = pp->textList((Poppler::Page::Rotation)d->currentRequest->documentRotation); } delete pp; // 3. [UNLOCK] mutex d->generator->docLock.unlock(); // by ending the thread notifies the GUI thread that data is pending and can be read}#include "generator_pdf.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -