📄 generator_pdf.cpp.svn-base
字号:
i18n("Security") ); docInfo.set( "optimization", pdfdoc->isLinearized() ? i18n( "Yes" ) : i18n( "No" ), i18n("Optimized") ); docInfo.set( "pages", QString::number( pdfdoc->numPages() ), i18n("Pages") ); } else { // TODO not sure one can reach here, check and if it is not possible, remove the code docInfo.set( "title", i18n("Unknown"), i18n("Title") ); docInfo.set( "subject", i18n("Unknown"), i18n("Subject") ); docInfo.set( "author", i18n("Unknown"), i18n("Author") ); docInfo.set( "keywords", i18n("Unknown"), i18n("Keywords") ); docInfo.set( "creator", i18n("Unknown"), i18n("Creator") ); docInfo.set( "producer", i18n("Unknown"), i18n("Producer") ); docInfo.set( "creationDate", i18n("Unknown Date"), i18n("Created") ); docInfo.set( "modificationDate", i18n("Unknown Date"), i18n("Modified") ); docInfo.set( "format", "PDF", i18n( "Format" ) ); docInfo.set( "encryption", i18n( "Unknown Encryption" ), i18n( "Security" ) ); docInfo.set( "optimization", i18n( "Unknown Optimization" ), i18n( "Optimized" ) ); docInfo.set( "pages", i18n("Unknown"), i18n("Pages") ); } docLock.unlock(); // if pdfdoc is valid then we cached good info -> don't cache them again if ( pdfdoc ) docInfoDirty = false; } return &docInfo;}const DocumentSynopsis * PDFGenerator::generateDocumentSynopsis(){ if ( !docSynopsisDirty ) return &docSyn; if ( !pdfdoc ) return NULL; docLock.lock(); QDomDocument *toc = pdfdoc->toc(); docLock.unlock(); if ( !toc ) return NULL; docSyn = DocumentSynopsis(); addSynopsisChildren(toc, &docSyn); delete toc; docSynopsisDirty = false; return &docSyn;}const DocumentFonts * PDFGenerator::generateDocumentFonts(){ if ( !docFontsDirty ) return &docFonts; // initialize fonts dom docFonts = DocumentFonts(); docFonts.appendChild( docFonts.createElement( "Fonts" ) ); docLock.lock(); QList<Poppler::FontInfo> fonts = pdfdoc->fonts(); docLock.unlock(); const QString fontTypeNames[8] = { i18n("unknown"), i18n("Type 1"), i18n("Type 1C"), i18n("Type 3"), i18n("TrueType"), i18n("CID Type 0"), i18n("CID Type 0C"), i18n("CID TrueType") }; foreach (const Poppler::FontInfo &font, fonts) { // 0. add font element QDomElement fontElem = docFonts.createElement( "font" ); docFonts.firstChild().appendChild( fontElem ); // 1. set Name const QString &name = font.name(); fontElem.setAttribute( "Name", name.isNull() ? i18n("[none]") : name ); // 2. set Type fontElem.setAttribute( "Type", fontTypeNames[ font.type() ] ); // 3. set Embedded fontElem.setAttribute( "Embedded", font.isEmbedded() ? i18n("Yes") : i18n("No") ); // 4. set Path fontElem.setAttribute( "File", font.file() ); } return &docFonts;}const QList<EmbeddedFile*> *PDFGenerator::embeddedFiles(){ if (docEmbeddedFilesDirty) { docLock.lock(); const QList<Poppler::EmbeddedFile*> &popplerFiles = pdfdoc->embeddedFiles(); foreach(Poppler::EmbeddedFile* pef, popplerFiles) { docEmbeddedFiles.append(new PDFEmbeddedFile(pef)); } docLock.unlock(); docEmbeddedFilesDirty = false; } return &docEmbeddedFiles;}bool PDFGenerator::isAllowed( int permissions ){#if !OKULAR_FORCE_DRM if (KAuthorized::authorize("skip_drm") && !KpdfSettings::obeyDRM()) return true;#endif bool b = true; if (permissions & KPDFDocument::AllowModify) b = b && pdfdoc->okToChange(); if (permissions & KPDFDocument::AllowCopy) b = b && pdfdoc->okToCopy(); if (permissions & KPDFDocument::AllowPrint) b = b && pdfdoc->okToPrint(); if (permissions & KPDFDocument::AllowNotes) b = b && pdfdoc->okToAddNotes(); return b;}bool PDFGenerator::canGeneratePixmap( bool /* async */){ return ready;}void PDFGenerator::generatePixmap( PixmapRequest * request ){#ifndef NDEBUG if ( !ready ) kDebug() << "calling generatePixmap() when not in READY state!" << endl;#endif // update busy state (not really needed here, because the flag needs to // be set only to prevent asking a pixmap while the thread is running) ready = false; // debug requests to this (xpdf) generator //kDebug() << "id: " << request->id << " is requesting " << (request->async ? "ASYNC" : "sync") << " pixmap for page " << request->page->number() << " [" << request->width << " x " << request->height << "]." << endl; /** asynchronous requests (generation in PDFPixmapGeneratorThread::run() **/ if ( request->async ) { // start the generation into the thread generatorThread->startGeneration( request ); return; } /** synchronous request: in-place generation **/ // compute dpi used to get an image with desired width and height KPDFPage * page = request->page; double fakeDpiX = request->width * 72.0 / page->width(), fakeDpiY = request->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() && (request->width == page->width()) && (request->height == page->height()); // generate links and image rects if rendering pages on pageview bool genObjectRects = request->id & (PAGEVIEW_ID | PRESENTATION_ID); // 0. LOCK [waits for the thread end] docLock.lock(); // 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()); // 2. Take data from outputdev and attach it to the Page page->setPixmap( request->id, p->splashRenderToPixmap(fakeDpiX, fakeDpiY, -1, -1, -1, -1, genObjectRects, (Poppler::Page::Rotation)m_document->rotation()) ); if ( genObjectRects ) { // TODO previously we extracted Image type rects too, but that needed porting to poppler // and as we are not doing anything with Image type rects i did not port it, have a look at // dead gp_outputdev.cpp on image extraction page->setObjectRects( generateKPDFLinks(p->links(), request->width, request->height, pdfdoc) ); } // 3. UNLOCK [re-enables shared access] docLock.unlock(); if ( genTextPage ) { QList<Poppler::TextBox*> textList = p->textList((Poppler::Page::Rotation)m_document->rotation()); page->setSearchPage( abstractTextPage(textList, page->height(), page->width(), page->orientation()) ); qDeleteAll(textList); } delete p; // update ready state ready = true; // notify the new generation signalRequestDone( request );}bool PDFGenerator::canGenerateTextPage(){ return true;}void PDFGenerator::generateSyncTextPage( KPDFPage * page ){// TODO i think this is wrong because we need the "optative rotation", not the original rotation, but AFAIK it's never called kDebug() << "calling generateSyncTextPage( KPDFPage * page )" << endl; // build a TextList... Poppler::Page *pp = pdfdoc->page( page->number() ); docLock.lock(); QList<Poppler::TextBox*> textList = pp->textList((Poppler::Page::Rotation)m_document->rotation()); docLock.unlock(); delete pp; // ..and attach it to the page page->setSearchPage( abstractTextPage(textList, page->height(), page->width(), page->orientation()) ); qDeleteAll(textList);}bool PDFGenerator::print( KPrinter& printer ){ int width, height; QString ps = printer.option("PageSize"); if (ps.indexOf(QRegExp("w\\d+h\\d+")) == 0) { // size not supported by Qt, KPrinter gives us the size as wWIDTHhHEIGHT // remove the w ps = ps.mid(1); int hPos = ps.indexOf("h"); width = ps.left(hPos).toInt(); height = ps.mid(hPos+1).toInt(); } else { // size is supported by Qt, we get either the pageSize name or nothing because the default pageSize is used QPrinter dummy(QPrinter::PrinterResolution); dummy.setFullPage(true); dummy.setPageSize((QPrinter::PageSize)(ps.isEmpty() ? KGlobal::locale()->pageSize() : pageNameToPageSize(ps))); width = dummy.width(); height = dummy.height(); } KTempFile tf( QString::null, ".ps" ); QList<int> pageList; if (!printer.previewOnly()) pageList = printer.pageList(); else for(int i = 1; i <= pdfdoc->numPages(); i++) pageList.push_back(i); docLock.lock(); // TODO rotation if (pdfdoc->print(tf.name(), pageList, 72, 72, 0, width, height)) { docLock.unlock(); printer.printFiles(QStringList(tf.name()), true); return true; } else { docLock.unlock(); return false; } return false;}QString PDFGenerator::getMetaData( const QString & key, const QString & option ){ if ( key == "StartFullScreen" ) { // asking for the 'start in fullscreen mode' (pdf property) if ( pdfdoc->pageMode() == Poppler::Document::FullScreen ) return "yes"; } else if ( key == "NamedViewport" && !option.isEmpty() ) { // asking for the page related to a 'named link destination'. the // option is the link name. @see addSynopsisChildren. DocumentViewport viewport; docLock.lock(); Poppler::LinkDestination *ld = pdfdoc->linkDestination( option ); docLock.unlock(); if ( ld ) { fillViewportFromLinkDestination( viewport, *ld, pdfdoc ); } delete ld; if ( viewport.pageNumber >= 0 ) return viewport.toString(); } else if ( key == "DocumentTitle" ) { docLock.lock(); QString title = pdfdoc->info( "Title" ); docLock.unlock(); return title; } return QString();}bool PDFGenerator::reparseConfig(){ // load paper color from Settings or use the white default color QColor color = ( (KpdfSettings::renderMode() == KpdfSettings::EnumRenderMode::Paper ) && KpdfSettings::changeColors() ) ? KpdfSettings::paperColor() : Qt::white; // if paper color is changed we have to rebuild every visible pixmap in addition // to the outputDevice. it's the 'heaviest' case, other effect are just recoloring // over the page rendered on 'standard' white background. if ( pdfdoc && color != pdfdoc->paperColor() ) { docLock.lock(); pdfdoc->setPaperColor(color); docLock.unlock(); return true; } return false;}bool PDFGenerator::exportToText( const QString & fileName ){ QFile f( fileName ); if ( !f.open( QIODevice::WriteOnly ) ) return false; QTextStream ts( &f ); int num = m_document->pages(); for ( int i = 0; i < num; ++i ) { docLock.lock(); Poppler::Page *pp = pdfdoc->page(i); QString text = pp->text(QRect()); docLock.unlock(); ts << text; delete pp; } f.close(); return true;}//END Generator inherited functionsinline void append (KPDFTextPage* ktp, QString s, double l, double b, double r, double t){// kWarning() << "text: " << s << " at (" << l << "," << t << ")x(" << r <<","<<b<<")" << endl; ktp->append( s , new NormalizedRect( l, t, r, b ));}KPDFTextPage * PDFGenerator::abstractTextPage(const QList<Poppler::TextBox*> &text, double height, double width,int rot){ KPDFTextPage* ktp=new KPDFTextPage; Poppler::TextBox *next; kWarning() << "getting text page in generator pdf - rotation: " << rot << endl; int charCount=0; int j; QString s; NormalizedRect * wordRect = new NormalizedRect; rot = (rot + m_document->rotation()) % 4; foreach (Poppler::TextBox *word, text) { wordRect->left = word->boundingBox().left(); wordRect->bottom = word->boundingBox().bottom(); wordRect->right = word->boundingBox().right(); wordRect->top = word->boundingBox().top(); charCount=word->text().length(); next=word->nextWord(); switch (rot) { case 0: // 0 degrees, normal word boundaries are top and bottom // only x boundaries change the order of letters is normal not reversed for (j = 0; j < charCount; j++) { s = word->text().at(j); append(ktp, (j==charCount-1 && !next ) ? (s + '\n') : s, // this letters boundary word->edge(j)/width, wordRect->bottom/height, // next letters boundary word->edge(j+1)/width, wordRect->top/height); } if ( word->hasSpaceAfter() && next ) append(ktp, " ", // this letters boundary word->edge(charCount)/width, wordRect->bottom/height, // next letters boundary next->edge(0)/width, wordRect->top/height); break; case 1: // 90 degrees, x boundaries not changed // y ones change, the order of letters is normal not reversed for (j=0;j<charCount;j++) { s=word->text().at(j); append(ktp, (j==charCount-1 && !next ) ? (s + '\n') : s, wordRect->left/width, word->edge(j)/height, wordRect->right/width, word->edge(j+1)/height); } if ( word->hasSpaceAfter() && next ) append(ktp, " ", // this letters boundary wordRect->left/width, word->edge(charCount)/height, // next letters boundary wordRect->right/width, next->edge(0)/height);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -