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; }
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; }