void RenderThread::run() { double factor = qBound(0.01, m_zoomFactor, 10.0); if (!QFile::exists(m_pdfUrl)) return; Poppler::Document* document = Poppler::Document::load(m_pdfUrl); if (!document || document->isLocked()) { delete document; return; } // Access page of the PDF file document->setRenderHint(Poppler::Document::Antialiasing, true); document->setRenderHint(Poppler::Document::TextAntialiasing, true); Poppler::Page* pdfPage = document->page(0); // Document starts at page 0 if (pdfPage == 0) { return; } // Generate a QImage of the rendered page QImage image = pdfPage->renderToImage(factor*200.0, factor*200.0); emit previewReady(image); delete pdfPage; delete document; }
void TestLinks::checkDests_xr01() { Poppler::Document *doc; doc = Poppler::Document::load(TESTDATADIR "/unittestcases/xr01.pdf"); QVERIFY( doc ); Poppler::Page *page = doc->page(0); QVERIFY( page ); QList< Poppler::Link* > links = page->links(); QCOMPARE( links.count(), 2 ); { QCOMPARE( links.at(0)->linkType(), Poppler::Link::Goto ); Poppler::LinkGoto *link = static_cast< Poppler::LinkGoto * >( links.at(0) ); const Poppler::LinkDestination dest = link->destination(); QVERIFY( !isDestinationValid_pageNumber( &dest, doc ) ); QVERIFY( isDestinationValid_name( &dest ) ); QCOMPARE( dest.destinationName(), QString::fromLatin1("section.1") ); } { QCOMPARE( links.at(1)->linkType(), Poppler::Link::Goto ); Poppler::LinkGoto *link = static_cast< Poppler::LinkGoto * >( links.at(1) ); const Poppler::LinkDestination dest = link->destination(); QVERIFY( !isDestinationValid_pageNumber( &dest, doc ) ); QVERIFY( isDestinationValid_name( &dest ) ); QCOMPARE( dest.destinationName(), QString::fromLatin1("section.2") ); } delete doc; }
void SearchDocumentJob::run() { Q_ASSERT(m_document); for (int i = 0; i < m_document->numPages(); ++i) { int ipage = (startPage + i) % m_document->numPages(); Poppler::Page *page = m_document->page(ipage); double sLeft, sTop, sRight, sBottom; float scaleW = 1.f / page->pageSizeF().width(); float scaleH = 1.f / page->pageSizeF().height(); bool found; found = page->search(m_search, sLeft, sTop, sRight, sBottom, Poppler::Page::FromTop, Poppler::Page::IgnoreCase); while (found) { QRectF result; result.setLeft(sLeft * scaleW); result.setTop(sTop * scaleH); result.setRight(sRight * scaleW); result.setBottom(sBottom * scaleH); m_matches.append(QPair<int, QRectF>(ipage, result)); found = page->search(m_search, sLeft, sTop, sRight, sBottom, Poppler::Page::NextResult, Poppler::Page::IgnoreCase); } delete page; } }
WINPrint::~WINPrint() { if (!doit) return; Poppler::Document* document = Poppler::Document::load(file); if (document) { document->setRenderHint(Poppler::Document::Antialiasing); document->setRenderHint(Poppler::Document::TextAntialiasing); int nbpages=document->numPages(), nextpage=nbpages-1; QPainter Paint; if(Paint.begin(Prt)) { QImage image; QRect rect (0, 0, Prt->paperRect (QPrinter::DevicePixel).width(), Prt->paperRect(QPrinter::DevicePixel).height()); double rres= Prt->resolution(); Paint.setRenderHint (QPainter::Antialiasing); for (int pg=0;pg < nbpages;pg++) { Poppler::Page* pdfPage = document->page (pg); if (pdfPage) { image= pdfPage->renderToImage (rres, rres); delete pdfPage; } if (!image.isNull()) { Paint.drawImage (rect, image); if (pg != nextpage) Prt->newPage(); } else convert_error << "Fail to create image at " << rres << " dpi resolution\n"; } Paint.end(); } delete (document); } }
void guFolderInspector::extractIsbnsFromPdf(QString fileName, QList<QString> &ISBNList) { //PDFDoc *doc; //doc = new PDFDoc() //qDebug() << "file:" << fileName; Poppler::Document* document; document = Poppler::Document::load(fileName,0,0); //Poppler::Document:: if (!document || document->isLocked()) { // ... error message .... delete document; return; } // Paranoid safety check if (!document) { // ... error message ... return; } Poppler::Page* pdfPage; isbnMethods find; // Access page of the PDF file int numOfPages = document->numPages(); //количество страниц int numOfSearchPages = 15; //qDebug() << "num of pages " << numOfPages; if(numOfPages < numOfSearchPages) { numOfSearchPages = numOfPages; } for ( int pageNumber = 0 ; pageNumber < numOfSearchPages ; pageNumber++) { pdfPage = document->page(pageNumber); // Document starts at page 0 if (!pdfPage) { // ... error message ... continue; } //QtMsgHandler qInstallMsgHandler ( QtMsgHandler handler ) QString pageContent; pageContent = pdfPage->text(QRectF(QPointF(0,0),pdfPage->pageSizeF())); find.findIsbns(pageContent, ISBNList); // ... use image ... //qDebug() << pageContent; } // after the usage, the page must be deleted delete pdfPage; //Finally, don't forget to destroy the document: delete document; }
void Renderer::fillTestSlideSize(int slideNumber) { if (!this->loadedTestSlides->at(slideNumber)) { Poppler::Page * testPage = this->document->page(slideNumber); Slide *testSlide = new Slide(testPage->renderToImage(TEST_DPI, TEST_DPI), QRect()); this->testSlides->replace(slideNumber,testSlide); this->loadedTestSlides->replace(slideNumber,true); delete testPage; } }
int main( int argc, char **argv ) { QApplication a( argc, argv ); // QApplication required! QTime t; t.start(); QDir directory( argv[1] ); foreach ( const QString &fileName, directory.entryList() ) { if (fileName.endsWith("pdf") ) { qDebug() << "Doing" << fileName.toLatin1().data() << ":"; Poppler::Document *doc = Poppler::Document::load( directory.canonicalPath()+"/"+fileName ); if (!doc) { qWarning() << "doc not loaded"; } else if ( doc->isLocked() ) { if (! doc->unlock( "", "password" ) ) { qWarning() << "couldn't unlock document"; delete doc; } } else { doc->pdfVersion(); doc->info("Title"); doc->info("Subject"); doc->info("Author"); doc->info("Keywords"); doc->info("Creator"); doc->info("Producer"); doc->date("CreationDate").toString(); doc->date("ModDate").toString(); doc->numPages(); doc->isLinearized(); doc->isEncrypted(); doc->okToPrint(); doc->okToCopy(); doc->okToChange(); doc->okToAddNotes(); doc->pageMode(); for( int index = 0; index < doc->numPages(); ++index ) { Poppler::Page *page = doc->page( index ); QImage image = page->renderToImage(); page->pageSize(); page->orientation(); delete page; std::cout << "."; std::cout.flush(); } std::cout << std::endl; delete doc; } } } std::cout << "Elapsed time: " << (t.elapsed()/1000) << "seconds" << std::endl; }
void PageSizesJob::run() { Q_ASSERT(m_document); for (int i = 0; i < m_document->numPages(); ++i) { Poppler::Page *page = m_document->page(i); m_pageSizes.append(page->pageSizeF()); delete page; } }
void RenderPageJob::run() { Q_ASSERT(m_document); Poppler::Page *page = m_document->page(m_index); float scale = 72.0f * (float(m_width) / page->pageSizeF().width()); QImage image = page->renderToImage(scale, scale); // Note: assuming there's exactly one handler (PDFCanvas) to catch ownership of this when PDFDocument emits a signal with this m_page = m_window->createTextureFromImage(image); delete page; }
void pdfBoard::updateBoard() { Poppler::Page *pg = pdf->page( currentPage ); if ( pg == 0 ) return; QImage image = pg->renderToImage( 72*zoom, 72*zoom, x, y, 600, 800 ); if ( image.isNull() ) return; setMinimumSize(600, 800); setMaximumSize(600, 800); setPixmap( QPixmap::fromImage( image ) ); show(); delete pg; }
void TestMetaData::checkSeascapeOrientation() { Poppler::Document *doc; doc = Poppler::Document::load("../../../test/unittestcases/orientation.pdf"); QVERIFY( doc ); Poppler::Page *page = doc->page(3); QCOMPARE( page->orientation(), Poppler::Page::Seascape ); delete page; delete doc; }
Slide *Renderer::renderSlide(int slideNumber, QRect geometry) { this->fillTestSlideSize(slideNumber); Slide *testSlide = this->testSlides->at(slideNumber); QPoint scaleFactor = testSlide->computeScaleFactor(geometry, TEST_DPI); Poppler::Page * pdfPage = this->document->page(slideNumber); QImage image = pdfPage->renderToImage(scaleFactor.x(),scaleFactor.y()); delete pdfPage; return new Slide(image, geometry); }
void TestMetaData::checkPageSize() { Poppler::Document *doc; doc = Poppler::Document::load("../../../test/unittestcases/truetype.pdf"); QVERIFY( doc ); Poppler::Page *page = doc->page(0); QCOMPARE( page->pageSize(), QSize(595, 842) ); QCOMPARE( page->pageSizeF(), QSizeF(595.22, 842) ); delete page; delete doc; }
int main( int argc, char **argv ) { QApplication a( argc, argv ); // QApplication required! if ( argc != 3) { qWarning() << "usage: test-password-qt4 owner-password filename"; exit(1); } Poppler::Document *doc = Poppler::Document::load(argv[2], argv[1]); if (!doc) { qWarning() << "doc not loaded"; exit(1); } // output some meta-data int major = 0, minor = 0; doc->getPdfVersion( &major, &minor ); qDebug() << " PDF Version: " << qPrintable(QString::fromLatin1("%1.%2").arg(major).arg(minor)); qDebug() << " Title: " << doc->info("Title"); qDebug() << " Subject: " << doc->info("Subject"); qDebug() << " Author: " << doc->info("Author"); qDebug() << " Key words: " << doc->info("Keywords"); qDebug() << " Creator: " << doc->info("Creator"); qDebug() << " Producer: " << doc->info("Producer"); qDebug() << " Date created: " << doc->date("CreationDate").toString(); qDebug() << " Date modified: " << doc->date("ModDate").toString(); qDebug() << "Number of pages: " << doc->numPages(); qDebug() << " Linearised: " << doc->isLinearized(); qDebug() << " Encrypted: " << doc->isEncrypted(); qDebug() << " OK to print: " << doc->okToPrint(); qDebug() << " OK to copy: " << doc->okToCopy(); qDebug() << " OK to change: " << doc->okToChange(); qDebug() << "OK to add notes: " << doc->okToAddNotes(); qDebug() << " Page mode: " << doc->pageMode(); QStringList fontNameList; foreach( const Poppler::FontInfo &font, doc->fonts() ) fontNameList += font.name(); qDebug() << " Fonts: " << fontNameList.join( ", " ); Poppler::Page *page = doc->page(0); qDebug() << " Page 1 size: " << page->pageSize().width()/72 << "inches x " << page->pageSize().height()/72 << "inches"; PDFDisplay test( doc ); // create picture display test.setWindowTitle("Poppler-Qt4 Test"); test.show(); // show it return a.exec(); // start event loop }
void PDFDisplay::display() { if (doc) { Poppler::Page *page = doc->getPage(currentPage); if (page) { delete pixmap; page->renderToPixmap(&pixmap, -1, -1, -1, -1); delete page; update(); } } else { printf("doc not loaded\n"); } }
void PDFDisplay::display() { if (doc) { Poppler::Page *page = doc->page(m_currentPage); if (page) { qDebug() << "Displaying page: " << m_currentPage; image = page->renderToImage(); update(); delete page; } } else { qWarning() << "doc not loaded"; } }
void TestActualText::checkActualText1() { Poppler::Document *doc; doc = Poppler::Document::load("../../../test/unittestcases/WithActualText.pdf"); QVERIFY( doc ); Poppler::Page *page = doc->page(0); QVERIFY( page ); QCOMPARE( page->text(QRectF()), QString("The slow brown fox jumps over the black dog.") ); delete page; delete doc; }
/* === private method implementation ========= */ QImage PdfImageGenerator::generateImage(const int &pno) { Poppler::Page* pdfPage = this->pdfDocument->page(pno); QImage image; if (pdfPage) { if (!pageSize.isValid()) { image = pdfPage->renderToImage(dpiX * scaleFactor, dpiY * scaleFactor); } else { image = pdfPage->renderToImage(dpiX * scaleFactor, dpiY * scaleFactor, -1, -1, pageSize.width(), pageSize.height()); } delete pdfPage; } return image; }
void KisPDFImportWidget::updateMaxCanvasSize() { m_maxWidthInch = 0., m_maxHeightInch = 0.; for (QList<int>::const_iterator it = m_pages.constBegin(); it != m_pages.constEnd(); ++it) { Poppler::Page *p = m_pdfDoc->page(*it); QSizeF size = p->pageSizeF(); if (size.width() > m_maxWidthInch) { m_maxWidthInch = size.width(); } if (size.height() > m_maxHeightInch) { m_maxHeightInch = size.height(); } } m_maxWidthInch /= 72.; m_maxHeightInch /= 72.; dbgFile << m_maxWidthInch << "" << m_maxHeightInch; updateResolution(); }
QImage Pdf::page(int i) { QImage image; // Paranoid safety check if (_document == 0) { return image; } Poppler::Page* pdfPage = _document->page(i); // Document starts at page 0 if (pdfPage == 0) { return image; } QSize size = pdfPage->pageSize(); float scale = 2.0; // the size can be decided more intelligently image = pdfPage->renderToImage(scale*72.0, scale*72.0, 0, 0, scale*size.width(), scale*size.height()); delete pdfPage; return binarization(image); }
int main(int argc, char **argv) { if (argc != 2) { std::cout << "Usage: " << argv[0] << " PDF" << std::endl; return 1; } QString filename(argv[1]); Poppler::Document* document = Poppler::Document::load(filename); document->setRenderHint(Poppler::Document::TextHinting, true); document->setRenderHint(Poppler::Document::TextSlightHinting, true); Poppler::Page* pdfPage = document->page(0); // dpi must be high enough QImage image = pdfPage->renderToImage(200, 200); return 0; }
void PDFDisplay::display() { if (doc) { Poppler::Page *page = doc->page(m_currentPage); if (page) { qDebug() << "Displaying page using" << backendString << "backend: " << m_currentPage; image = page->renderToImage(); qDeleteAll(textRects); if (showTextRects) { QPainter painter(&image); painter.setPen(Qt::red); textRects = page->textList(); foreach(Poppler::TextBox *tb, textRects) { painter.drawRect(tb->boundingBox()); } } else textRects.clear(); update(); delete page; }
int main( int argc, char **argv ) { QApplication a( argc, argv ); // QApplication required! if ( argc < 2 || (argc == 3 && strcmp(argv[2], "-extract") != 0) || argc > 3) { // use argument as file name printf("usage: test-poppler-qt filename [-extract]\n"); exit(1); } Poppler::Document *doc = Poppler::Document::load(argv[1]); if (!doc) { printf("doc not loaded\n"); exit(1); } if (argc == 2) { PDFDisplay test( doc ); // create picture display a.setMainWidget( &test); // set main widget test.setCaption("Poppler-Qt Test"); test.show(); // show it return a.exec(); // start event loop } else { Poppler::Page *page = doc->getPage(0); QLabel *l = new QLabel(page->getText(Poppler::Rectangle()), 0); l->show(); a.setMainWidget(l); // set main widget delete page; delete doc; return a.exec(); } }
int main( int argc, char **argv ) { QApplication a( argc, argv ); // QApplication required! if ( argc < 2 || (argc == 3 && strcmp(argv[2], "-arthur") != 0) || argc > 3) { // use argument as file name qWarning() << "usage: test-poppler-qt4 filename [-arthur]"; exit(1); } Poppler::Document *doc = Poppler::Document::load(QFile::decodeName(argv[1])); if (!doc) { qWarning() << "doc not loaded"; exit(1); } if (doc->isLocked()) { qWarning() << "document locked (needs password)"; exit(0); } if (doc->numPages() <= 0) { delete doc; qDebug() << "Doc has no pages"; return 0; } QString backendString; if (argc == 3 && strcmp(argv[2], "-arthur") == 0) { backendString = "Arthur"; doc->setRenderBackend(Poppler::Document::ArthurBackend); } else { backendString = "Splash"; doc->setRenderBackend(Poppler::Document::SplashBackend); } doc->setRenderHint(Poppler::Document::Antialiasing, true); doc->setRenderHint(Poppler::Document::TextAntialiasing, true); for (int i = 0; i < doc->numPages(); ++i) { Poppler::Page *page = doc->page(i); if (page) { qDebug() << "Rendering page using" << backendString << "backend: " << i; QTime t = QTime::currentTime(); QImage image = page->renderToImage(); qDebug() << "Rendering took" << t.msecsTo(QTime::currentTime()) << "msecs"; image.save(QString("test-rennder-to-file%1.ppm").arg(i)); delete page; } } return 0; }
void SearchWorker::run() { while (1) { bar->search_mutex.lock(); stop = false; if (die) { break; } // always clear results -> empty search == stop search emit clear_hits(); // get search string bar->term_mutex.lock(); if (bar->term.isEmpty()) { bar->term_mutex.unlock(); emit update_label_text("done."); continue; } int start = bar->start_page; QString search_term = bar->term; forward = bar->forward; bar->term_mutex.unlock(); // check if term contains upper case letters; if so, do case sensitive search (smartcase) bool has_upper_case = false; for (QString::const_iterator it = search_term.begin(); it != search_term.end(); ++it) { if (it->isUpper()) { has_upper_case = true; break; } } #ifdef DEBUG cerr << "'" << search_term.toUtf8().constData() << "'" << endl; #endif emit update_label_text(QString("[%1] 0\% searched, 0 hits") .arg(has_upper_case ? "Case" : "no case")); // search all pages int hit_count = 0; int page = start; do { Poppler::Page *p = bar->doc->page(page); if (p == NULL) { cerr << "failed to load page " << page << endl; continue; } // collect all occurrences QList<QRectF> *hits = new QList<QRectF>; #if POPPLER_VERSION < POPPLER_VERSION_CHECK(0, 22, 0) // old search interface, slow for many hits per page double x = 0, y = 0, x2 = 0, y2 = 0; while (!stop && !die && p->search(search_term, x, y, x2, y2, Poppler::Page::NextResult, has_upper_case ? Poppler::Page::CaseSensitive : Poppler::Page::CaseInsensitive)) { hits->push_back(QRectF(x, y, x2 - x, y2 - y)); } #elif POPPLER_VERSION < POPPLER_VERSION_CHECK(0, 31, 0) // new search interface QList<QRectF> tmp = p->search(search_term, has_upper_case ? Poppler::Page::CaseSensitive : Poppler::Page::CaseInsensitive); hits->swap(tmp); #else // even newer interface QList<QRectF> tmp = p->search(search_term, has_upper_case ? (Poppler::Page::SearchFlags) 0 : Poppler::Page::IgnoreCase); // TODO support Poppler::Page::WholeWords hits->swap(tmp); #endif #ifdef DEBUG if (hits->size() > 0) { cerr << hits->size() << " hits on page " << page << endl; } #endif delete p; // clean up when interrupted if (stop || die) { delete hits; break; } if (hits->size() > 0) { hit_count += hits->size(); emit search_done(page, hits); } else { delete hits; } // update progress label next to the search bar int percent; if (forward) { percent = page + bar->doc->numPages() - start; } else { percent = start + bar->doc->numPages() - page; } percent = (percent % bar->doc->numPages()) * 100 / bar->doc->numPages(); QString progress = QString("[%1] %2\% searched, %3 hits") .arg(has_upper_case ? "Case" : "no case") .arg(percent) .arg(hit_count); emit update_label_text(progress); if (forward) { if (++page == bar->doc->numPages()) { page = 0; } } else { if (--page == -1) { page = bar->doc->numPages() - 1; } } } while (page != start); #ifdef DEBUG cerr << "done!" << endl; #endif emit update_label_text(QString("[%1] done, %2 hits") .arg(has_upper_case ? "Case" : "no case") .arg(hit_count)); } }
int main( int argc, char **argv ) { QApplication a( argc, argv ); // QApplication required! Q_UNUSED( argc ); Q_UNUSED( argv ); QTime t; t.start(); QDir dbDir( QStringLiteral( "./pdfdb" ) ); if ( !dbDir.exists() ) { qWarning() << "Database directory does not exist"; } QStringList excludeSubDirs; excludeSubDirs << QStringLiteral("000048") << QStringLiteral("000607"); const QStringList dirs = dbDir.entryList(QStringList() << QStringLiteral("0000*"), QDir::Dirs); foreach ( const QString &subdir, dirs ) { if ( excludeSubDirs.contains(subdir) ) { // then skip it } else { QString path = "./pdfdb/" + subdir + "/data.pdf"; std::cout <<"Doing " << path.toLatin1().data() << " :"; Poppler::Document *doc = Poppler::Document::load( path ); if (!doc) { qWarning() << "doc not loaded"; } else { int major = 0, minor = 0; doc->getPdfVersion( &major, &minor ); doc->info(QStringLiteral("Title")); doc->info(QStringLiteral("Subject")); doc->info(QStringLiteral("Author")); doc->info(QStringLiteral("Keywords")); doc->info(QStringLiteral("Creator")); doc->info(QStringLiteral("Producer")); doc->date(QStringLiteral("CreationDate")).toString(); doc->date(QStringLiteral("ModDate")).toString(); doc->numPages(); doc->isLinearized(); doc->isEncrypted(); doc->okToPrint(); doc->okToCopy(); doc->okToChange(); doc->okToAddNotes(); doc->pageMode(); for( int index = 0; index < doc->numPages(); ++index ) { Poppler::Page *page = doc->page( index ); page->renderToImage(); page->pageSize(); page->orientation(); delete page; std::cout << "."; std::cout.flush(); } std::cout << std::endl; delete doc; } } } std::cout << "Elapsed time: " << (t.elapsed()/1000) << std::endl; }
void Worker::run() { while (1) { res->requestSemaphore.acquire(1); if (die) { break; } // get next page to render res->requestMutex.lock(); int page, width, index; map<int,pair<int,int> >::iterator less = res->requests.lower_bound(res->center_page); map<int,pair<int,int> >::iterator greater = less--; if (greater != res->requests.end()) { if (greater != res->requests.begin()) { // favour nearby page, go down first if (greater->first + less->first <= res->center_page * 2) { page = greater->first; index = greater->second.first; width = greater->second.second; res->requests.erase(greater); } else { page = less->first; index = less->second.first; width = less->second.second; res->requests.erase(less); } } else { page = greater->first; index = greater->second.first; width = greater->second.second; res->requests.erase(greater); } } else { page = less->first; index = less->second.first; width = less->second.second; res->requests.erase(less); } res->requestMutex.unlock(); // check for duplicate requests res->k_page[page].mutex.lock(); if (res->k_page[page].status[index] == width && res->k_page[page].rotation[index] == res->rotation) { res->k_page[page].mutex.unlock(); continue; } int rotation = res->rotation; res->k_page[page].mutex.unlock(); // open page #ifdef DEBUG cerr << " rendering page " << page << " for index " << index << endl; #endif Poppler::Page *p = res->doc->page(page); if (p == NULL) { cerr << "failed to load page " << page << endl; continue; } // render page float dpi = 72.0 * width / res->get_page_width(page); QImage img = p->renderToImage(dpi, dpi, -1, -1, -1, -1, static_cast<Poppler::Page::Rotation>(rotation)); if (img.isNull()) { cerr << "failed to render page " << page << endl; continue; } // invert to current color setting if (res->inverted_colors) { img.invertPixels(); } // put page res->k_page[page].mutex.lock(); if (!res->k_page[page].img[index].isNull()) { res->k_page[page].img[index] = QImage(); // assign null image } // adjust all available images to current color setting if (res->k_page[page].inverted_colors != res->inverted_colors) { res->k_page[page].inverted_colors = res->inverted_colors; for (int i = 0; i < 3; i++) { res->k_page[page].img[i].invertPixels(); } res->k_page[page].thumbnail.invertPixels(); } res->k_page[page].img[index] = img; res->k_page[page].status[index] = width; res->k_page[page].rotation[index] = rotation; res->k_page[page].mutex.unlock(); res->garbageMutex.lock(); res->garbage.insert(page); // TODO add index information? res->garbageMutex.unlock(); emit page_rendered(page); // collect goto links res->link_mutex.lock(); if (res->k_page[page].links == NULL) { res->link_mutex.unlock(); QList<Poppler::Link *> *links = new QList<Poppler::Link *>; QList<Poppler::Link *> l = p->links(); links->swap(l); res->link_mutex.lock(); res->k_page[page].links = links; } if (res->k_page[page].text == NULL) { res->link_mutex.unlock(); QList<Poppler::TextBox *> text = p->textList(); // assign boxes to lines // make single parts from chained boxes set<Poppler::TextBox *> used; QList<SelectionPart *> selection_parts; Q_FOREACH(Poppler::TextBox *box, text) { if (used.find(box) != used.end()) { continue; } used.insert(box); SelectionPart *p = new SelectionPart(box); selection_parts.push_back(p); Poppler::TextBox *next = box->nextWord(); while (next != NULL) { used.insert(next); p->add_word(next); next = next->nextWord(); } } // sort by y coordinate qStableSort(selection_parts.begin(), selection_parts.end(), selection_less_y); QRectF line_box; QList<SelectionLine *> *lines = new QList<SelectionLine *>(); Q_FOREACH(SelectionPart *part, selection_parts) { QRectF box = part->get_bbox(); // box fits into line_box's line if (!lines->empty() && box.y() <= line_box.center().y() && box.bottom() > line_box.center().y()) { float ratio_w = box.width() / line_box.width(); float ratio_h = box.height() / line_box.height(); if (ratio_w < 1.0f) { ratio_w = 1.0f / ratio_w; } if (ratio_h < 1.0f) { ratio_h = 1.0f / ratio_h; } if (ratio_w > 1.3f && ratio_h > 1.3f) { lines->back()->sort(); lines->push_back(new SelectionLine(part)); line_box = part->get_bbox(); } else { lines->back()->add_part(part); } // it doesn't fit, create new line } else { if (!lines->empty()) { lines->back()->sort(); } lines->push_back(new SelectionLine(part)); line_box = part->get_bbox(); } } if (!lines->empty()) { lines->back()->sort(); } res->link_mutex.lock(); res->k_page[page].text = lines; }