void Model::DjVuDocument::loadProperties(QStandardItemModel* propertiesModel) const { Document::loadProperties(propertiesModel); QMutexLocker mutexLocker(&m_mutex); propertiesModel->setColumnCount(2); miniexp_t annoExp; while(true) { annoExp = ddjvu_document_get_anno(m_document, TRUE); if(annoExp == miniexp_dummy) { clearMessageQueue(m_context, true); } else { break; } } const int annoLength = miniexp_length(annoExp); for(int annoN = 0; annoN < annoLength; ++annoN) { miniexp_t listExp = miniexp_nth(annoN, annoExp); const int listLength = miniexp_length(listExp); if(listLength <= 1 || qstrncmp(miniexp_to_name(miniexp_nth(0, listExp)), "metadata", 8) != 0) { continue; } for(int listN = 1; listN < listLength; ++listN) { miniexp_t keyValueExp = miniexp_nth(listN, listExp); if(miniexp_length(keyValueExp) != 2) { continue; } const QString key = QString::fromUtf8(miniexp_to_name(miniexp_nth(0, keyValueExp))); const QString value = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, keyValueExp))); if(!key.isEmpty() && !value.isEmpty()) { propertiesModel->appendRow(QList< QStandardItem* >() << new QStandardItem(key) << new QStandardItem(value)); } } } ddjvu_miniexp_release(m_document, annoExp); }
jint* get_djvu_hyperlink_area(ddjvu_pageinfo_t *page_info, miniexp_t sexp, int &type, int &len) { miniexp_t iter; iter = sexp; DEBUG("Hyperlink area %s", miniexp_to_name(miniexp_car(sexp))); if (miniexp_car(iter) == miniexp_symbol("rect")) type = 1; else if (miniexp_car(iter) == miniexp_symbol("oval")) type = 2; else if (miniexp_car(iter) == miniexp_symbol("poly")) type = 3; else return NULL; len = miniexp_length(iter); jint* array = new jint[len]; int x, i = 0; iter = miniexp_cdr(iter); while (iter != miniexp_nil) { if (!number_from_miniexp(miniexp_car(iter), &x)) break; iter = miniexp_cdr(iter); array[i++] = (jint) x; if (i >= len) break; } len = i; if ((type == 1 || type == 2) && len == 4) { int miny, width, height; miny = array[1]; width = array[2]; height = array[3]; array[1] = (page_info->height - (miny + height)); array[2] = array[0] + width; array[3] = (page_info->height - miny); } if (type == 3 && (len % 2) == 0) { int ccc; for (int k = 1; k < len; k += 2) { ccc = array[k]; array[k] = (page_info->height - ccc); } } return array; }
void declare_fun(llvm::Module* module, minivar_t name, minivar_t code) { llvm::IRBuilder<> builder(module->getContext()); llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getVoidTy(), false); llvm::Function *mainFunc = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, miniexp_to_name(name), module); llvm::BasicBlock *entry = llvm::BasicBlock::Create(module->getContext(), "entry", mainFunc); llvm::ReturnInst::Create(module->getContext(), entry); builder.SetInsertPoint(entry); }
static QString loadText(miniexp_t textExp, const QRect& rect, int pageHeight) { const int textLength = miniexp_length(textExp); if(textLength >= 6 && miniexp_symbolp(miniexp_nth(0, textExp))) { const int xmin = miniexp_to_int(miniexp_nth(1, textExp)); const int ymin = miniexp_to_int(miniexp_nth(2, textExp)); const int xmax = miniexp_to_int(miniexp_nth(3, textExp)); const int ymax = miniexp_to_int(miniexp_nth(4, textExp)); if(rect.intersects(QRect(xmin, pageHeight - ymax, xmax - xmin, ymax - ymin))) { if(qstrncmp(miniexp_to_name(miniexp_nth(0, textExp)), "word", 4) == 0) { return QString::fromUtf8(miniexp_to_str(miniexp_nth(5, textExp))); } else { QStringList text; for(int textN = 5; textN < textLength; ++textN) { text.append(loadText(miniexp_nth(textN, textExp), rect, pageHeight)); } if(qstrncmp(miniexp_to_name(miniexp_nth(0, textExp)), "line", 4) == 0) { return text.join(" "); } else { return text.join("\n"); } } } } return QString(); }
static EvMapping * get_djvu_hyperlink_mapping (DjvuDocument *djvu_document, int page, ddjvu_pageinfo_t *page_info, miniexp_t sexp) { EvMapping *ev_link_mapping = NULL; EvLinkAction *ev_action = NULL; miniexp_t iter; const char *url, *url_target, *comment; ev_link_mapping = g_new (EvMapping, 1); iter = sexp; if (miniexp_car (iter) != miniexp_symbol ("maparea")) goto unknown_mapping; iter = miniexp_cdr(iter); if (miniexp_caar(iter) == miniexp_symbol("url")) { if (!string_from_miniexp (miniexp_cadr (miniexp_car (iter)), &url)) goto unknown_mapping; if (!string_from_miniexp (miniexp_caddr (miniexp_car (iter)), &url_target)) goto unknown_mapping; } else { if (!string_from_miniexp (miniexp_car(iter), &url)) goto unknown_mapping; url_target = NULL; } iter = miniexp_cdr (iter); if (!string_from_miniexp (miniexp_car(iter), &comment)) goto unknown_mapping; iter = miniexp_cdr (iter); if (!get_djvu_hyperlink_area (page_info, miniexp_car(iter), ev_link_mapping)) goto unknown_mapping; iter = miniexp_cdr (iter); /* FIXME: DjVu hyperlink attributes are ignored */ ev_action = get_djvu_link_action (djvu_document, url, page); if (!ev_action) goto unknown_mapping; ev_link_mapping->data = ev_link_new (comment, ev_action); g_object_unref (ev_action); return ev_link_mapping; unknown_mapping: if (ev_link_mapping) g_free(ev_link_mapping); g_warning("DjvuLibre error: Unknown hyperlink %s", miniexp_to_name(miniexp_car(sexp))); return NULL; }
void Model::DjVuDocument::loadOutline(QStandardItemModel* outlineModel) const { Document::loadOutline(outlineModel); QMutexLocker mutexLocker(&m_mutex); miniexp_t outlineExp; while(true) { outlineExp = ddjvu_document_get_outline(m_document); if(outlineExp == miniexp_dummy) { clearMessageQueue(m_context, true); } else { break; } } if(miniexp_length(outlineExp) <= 1) { return; } if(qstrncmp(miniexp_to_name(miniexp_nth(0, outlineExp)), "bookmarks", 9) != 0) { return; } ::loadOutline(outlineExp, 1, outlineModel->invisibleRootItem(), m_indexByName); ddjvu_miniexp_release(m_document, outlineExp); }
static gboolean get_djvu_hyperlink_area (ddjvu_pageinfo_t *page_info, miniexp_t sexp, EvMapping *ev_link_mapping) { miniexp_t iter; iter = sexp; if ((miniexp_car (iter) == miniexp_symbol ("rect") || miniexp_car (iter) == miniexp_symbol ("oval")) && miniexp_length (iter) == 5) { /* FIXME: get bounding box for (oval) since Evince doesn't support shaped links */ int minx, miny, width, height; iter = miniexp_cdr (iter); if (!number_from_miniexp (miniexp_car (iter), &minx)) goto unknown_link; iter = miniexp_cdr (iter); if (!number_from_miniexp (miniexp_car (iter), &miny)) goto unknown_link; iter = miniexp_cdr (iter); if (!number_from_miniexp (miniexp_car (iter), &width)) goto unknown_link; iter = miniexp_cdr (iter); if (!number_from_miniexp (miniexp_car (iter), &height)) goto unknown_link; ev_link_mapping->area.x1 = minx; ev_link_mapping->area.x2 = (minx + width); ev_link_mapping->area.y1 = (page_info->height - (miny + height)); ev_link_mapping->area.y2 = (page_info->height - miny); } else if (miniexp_car (iter) == miniexp_symbol ("poly") && miniexp_length (iter) >= 5 && miniexp_length (iter) % 2 == 1) { /* FIXME: get bounding box since Evince doesn't support shaped links */ int minx = G_MAXINT, miny = G_MAXINT; int maxx = G_MININT, maxy = G_MININT; iter = miniexp_cdr(iter); while (iter != miniexp_nil) { int x, y; if (!number_from_miniexp (miniexp_car(iter), &x)) goto unknown_link; iter = miniexp_cdr (iter); if (!number_from_miniexp (miniexp_car(iter), &y)) goto unknown_link; iter = miniexp_cdr (iter); minx = MIN (minx, x); miny = MIN (miny, y); maxx = MAX (maxx, x); maxy = MAX (maxy, y); } ev_link_mapping->area.x1 = minx; ev_link_mapping->area.x2 = maxx; ev_link_mapping->area.y1 = (page_info->height - maxy); ev_link_mapping->area.y2 = (page_info->height - miny); } else { /* unknown */ goto unknown_link; } return TRUE; unknown_link: g_warning("DjvuLibre error: Unknown hyperlink area %s", miniexp_to_name(miniexp_car(sexp))); return FALSE; }
QList< QRectF > Model::DjVuPage::search(const QString& text, bool matchCase) const { QMutexLocker mutexLocker(&m_parent->m_mutex); miniexp_t pageTextExp; while(true) { pageTextExp = ddjvu_document_get_pagetext(m_parent->m_document, m_index, "word"); if(pageTextExp == miniexp_dummy) { clearMessageQueue(m_parent->m_context, true); } else { break; } } QList< miniexp_t > words; QList< QRectF > results; words.append(pageTextExp); QRectF rect; int index = 0; while(!words.isEmpty()) { miniexp_t textExp = words.takeFirst(); const int textLength = miniexp_length(textExp); if(textLength >= 6 && miniexp_symbolp(miniexp_nth(0, textExp))) { if(qstrncmp(miniexp_to_name(miniexp_nth(0, textExp)), "word", 4) == 0) { const QString word = QString::fromUtf8(miniexp_to_str(miniexp_nth(5, textExp))); if(text.indexOf(word, index, matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive) == index) { const int xmin = miniexp_to_int(miniexp_nth(1, textExp)); const int ymin = miniexp_to_int(miniexp_nth(2, textExp)); const int xmax = miniexp_to_int(miniexp_nth(3, textExp)); const int ymax = miniexp_to_int(miniexp_nth(4, textExp)); rect = rect.united(QRectF(xmin, m_size.height() - ymax, xmax - xmin, ymax - ymin)); index += word.length(); while(text.length() > index && text.at(index).isSpace()) { ++index; } if(text.length() == index) { results.append(rect); rect = QRectF(); index = 0; } } else { rect = QRectF(); index = 0; } } else { for(int textN = 5; textN < textLength; ++textN) { words.append(miniexp_nth(textN, textExp)); } } } } ddjvu_miniexp_release(m_parent->m_document, pageTextExp); QTransform transform = QTransform::fromScale(72.0 / m_resolution, 72.0 / m_resolution); for(int index = 0; index < results.size(); ++index) { results[index] = transform.mapRect(results[index]); } return results; }
QList< Model::Link* > Model::DjVuPage::links() const { QMutexLocker mutexLocker(&m_parent->m_mutex); QList< Link* > links; miniexp_t pageAnnoExp; while(true) { pageAnnoExp = ddjvu_document_get_pageanno(m_parent->m_document, m_index); if(pageAnnoExp == miniexp_dummy) { clearMessageQueue(m_parent->m_context, true); } else { break; } } const int pageAnnoLength = miniexp_length(pageAnnoExp); for(int pageAnnoN = 0; pageAnnoN < pageAnnoLength; ++pageAnnoN) { miniexp_t linkExp = miniexp_nth(pageAnnoN, pageAnnoExp); if(miniexp_length(linkExp) <= 3 || qstrncmp(miniexp_to_name(miniexp_nth(0, linkExp)), "maparea", 7 ) != 0 || !miniexp_symbolp(miniexp_nth(0, miniexp_nth(3, linkExp)))) { continue; } const QString type = QString::fromUtf8(miniexp_to_name(miniexp_nth(0, miniexp_nth(3, linkExp)))); if(type == QLatin1String("rect") || type == QLatin1String("oval") || type == QLatin1String("poly")) { // boundary QPainterPath boundary; miniexp_t areaExp = miniexp_nth(3, linkExp); const int areaLength = miniexp_length( areaExp ); if(areaLength == 5 && (type == QLatin1String("rect") || type == QLatin1String("oval"))) { QPoint p(miniexp_to_int(miniexp_nth(1, areaExp)), miniexp_to_int(miniexp_nth(2, areaExp))); QSize s(miniexp_to_int(miniexp_nth(3, areaExp)), miniexp_to_int(miniexp_nth(4, areaExp))); p.setY(m_size.height() - s.height() - p.y()); const QRectF r(p, s); if(type == QLatin1String("rect")) { boundary.addRect(r); } else { boundary.addEllipse(r); } } else if(areaLength > 0 && areaLength % 2 == 1 && type == QLatin1String("poly")) { QPolygon polygon; for(int areaExpN = 1; areaExpN < areaLength; areaExpN += 2) { QPoint p(miniexp_to_int(miniexp_nth(areaExpN, areaExp)), miniexp_to_int(miniexp_nth(areaExpN + 1, areaExp))); p.setY(m_size.height() - p.y()); polygon << p; } boundary.addPolygon(polygon); } if(boundary.isEmpty()) { continue; } boundary = QTransform::fromScale(1.0 / m_size.width(), 1.0 / m_size.height()).map(boundary); // target QString target; miniexp_t targetExp = miniexp_nth(1, linkExp); if(miniexp_stringp(targetExp)) { target = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, linkExp))); } else if(miniexp_length(targetExp) == 3 && qstrncmp(miniexp_to_name(miniexp_nth(0, targetExp)), "url", 3) == 0) { target = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, targetExp))); } if(target.isEmpty()) { continue; } if(target.at(0) == QLatin1Char('#')) { target.remove(0, 1); bool ok = false; int targetPage = target.toInt(&ok); if(!ok) { if(m_parent->m_indexByName.contains(target)) { targetPage = m_parent->m_indexByName[target] + 1; } else { continue; } } else { targetPage = (target.at(0) == QLatin1Char('+') || target.at(0) == QLatin1Char('-')) ? m_index + targetPage : targetPage; } links.append(new Link(boundary, targetPage)); } else { links.append(new Link(boundary, target)); } } } ddjvu_miniexp_release(m_parent->m_document, pageAnnoExp); return links; }
jobject get_djvu_hyperlink_mapping(JNIEnv *jenv, ddjvu_document_t* djvu_document, ddjvu_pageinfo_t *page_info, miniexp_t sexp) { miniexp_t iter; const char *url, *url_target; jobject hl = NULL; iter = sexp; if (miniexp_car(iter) != miniexp_symbol("maparea")) { ERROR("DjvuLibre error: Unknown hyperlink %s", miniexp_to_name(miniexp_car(sexp))); return hl; } iter = miniexp_cdr(iter); if (miniexp_caar(iter) == miniexp_symbol("url")) { if (!string_from_miniexp(miniexp_cadr(miniexp_car(iter)), &url)) { ERROR("DjvuLibre error: Unknown hyperlink %s", miniexp_to_name(miniexp_car(sexp))); return hl; } if (!string_from_miniexp(miniexp_caddr(miniexp_car(iter)), &url_target)) { ERROR("DjvuLibre error: Unknown hyperlink %s", miniexp_to_name(miniexp_car(sexp))); return hl; } } else { if (!string_from_miniexp(miniexp_car(iter), &url)) { ERROR("DjvuLibre error: Unknown hyperlink %s", miniexp_to_name(miniexp_car(sexp))); return hl; } url_target = NULL; } iter = miniexp_cdr(iter); /* FIXME: DjVu hyperlink comments are ignored */ int len = 0; int type; jint* data; iter = miniexp_cdr(iter); if ((data = get_djvu_hyperlink_area(page_info, miniexp_car(iter), type, len)) == NULL) { ERROR("DjvuLibre error: Unknown hyperlink %s", miniexp_to_name(miniexp_car(sexp))); return hl; } iter = miniexp_cdr(iter); /* FIXME: DjVu hyperlink attributes are ignored */ DEBUG("DjvuLibre: Hyperlink url: %s url_target: %s", url, url_target); if (!url) { delete[] data; return hl; } jclass pagelinkClass = jenv->FindClass("org/ebookdroid/core/codec/PageLink"); if (!pagelinkClass) { delete[] data; return hl; } jmethodID plInitMethodId = jenv->GetMethodID(pagelinkClass, "<init>", "(Ljava/lang/String;I[I)V"); if (!plInitMethodId) { delete[] data; return hl; } jintArray points = jenv->NewIntArray(len); jenv->SetIntArrayRegion(points, 0, len, data); jstring jstr = jenv->NewStringUTF(url); hl = jenv->NewObject(pagelinkClass, plInitMethodId, jstr, (jint) type, points); jenv->DeleteLocalRef(jstr); jenv->DeleteLocalRef(points); delete[] data; // DEBUG("DjvuLibre: Hyperlink url: %s url_target: %s", url, url_target); return hl; }