static void loadOutline(miniexp_t outlineExp, int offset, QStandardItem* parent, const QHash< QString, int >& indexByName) { const int outlineLength = miniexp_length(outlineExp); for(int outlineN = qMax(0, offset); outlineN < outlineLength; ++outlineN) { miniexp_t bookmarkExp = miniexp_nth(outlineN, outlineExp); const int bookmarkLength = miniexp_length(bookmarkExp); if(bookmarkLength <= 1 || !miniexp_stringp(miniexp_nth(0, bookmarkExp)) || !miniexp_stringp(miniexp_nth(1, bookmarkExp))) { continue; } const QString title = QString::fromUtf8(miniexp_to_str(miniexp_nth(0, bookmarkExp))); QString destination = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, bookmarkExp))); if(!title.isEmpty() && !destination.isEmpty()) { if(destination.at(0) == QLatin1Char('#')) { destination.remove(0,1); bool ok = false; int destinationPage = destination.toInt(&ok); if(!ok) { if(indexByName.contains(destination)) { destinationPage = indexByName[destination] + 1; } else { continue; } } QStandardItem* item = new QStandardItem(title); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); item->setData(destinationPage, Qt::UserRole + 1); QStandardItem* pageItem = item->clone(); pageItem->setText(QString::number(destinationPage)); pageItem->setTextAlignment(Qt::AlignRight); parent->appendRow(QList< QStandardItem* >() << item << pageItem); if(bookmarkLength >= 3) { loadOutline(bookmarkExp, 2, item, indexByName); } } } } }
static int walkTableOfContent(lua_State *L, miniexp_t r, int *count, int depth) { depth++; miniexp_t lista = miniexp_cdr(r); // go inside bookmars in the list int length = miniexp_length(r); int counter = 0; const char* page_name; int page_number; while(counter < length-1) { lua_pushnumber(L, *count); lua_newtable(L); lua_pushstring(L, "page"); page_name = miniexp_to_str(miniexp_car(miniexp_cdr(miniexp_nth(counter, lista)))); if(page_name != NULL && page_name[0] == '#') { errno = 0; page_number = strtol(page_name + 1, NULL, 10); if(!errno) { lua_pushnumber(L, page_number); } else { /* we can not parse this as a number, TODO: parse page names */ lua_pushnumber(L, -1); } } else { /* something we did not expect here */ lua_pushnumber(L, -1); } lua_settable(L, -3); lua_pushstring(L, "depth"); lua_pushnumber(L, depth); lua_settable(L, -3); lua_pushstring(L, "title"); lua_pushstring(L, miniexp_to_str(miniexp_car(miniexp_nth(counter, lista)))); lua_settable(L, -3); lua_settable(L, -3); (*count)++; if (miniexp_length(miniexp_cdr(miniexp_nth(counter, lista))) > 1) { walkTableOfContent(L, miniexp_cdr(miniexp_nth(counter, lista)), count, depth); } counter++; } return 0; }
/** * djvu_text_page_selection_process_box: * @page: #DjvuTextPage instance * @p: s-expression to append bounding box of * @delimit: character/word/... delimiter * * Appends bounding box of the line containing miniexp_t to page->results * * Returns: whether the end was not reached in this s-expression */ static gboolean djvu_text_page_selection_process_box (DjvuTextPage *page, miniexp_t p, int delimit) { if (page->results || p == page->start) { EvRectangle box; const char *text; box.x1 = miniexp_to_int (miniexp_nth (1, p)); box.y1 = miniexp_to_int (miniexp_nth (2, p)); box.x2 = miniexp_to_int (miniexp_nth (3, p)); box.y2 = miniexp_to_int (miniexp_nth (4, p)); text = miniexp_to_str (miniexp_nth (5, p)); if (text != NULL && text[0] != '\0') { if (!(delimit & 2) && page->results != NULL) { EvRectangle *union_box = (EvRectangle *)page->results->data; /* If still on the same line, add box to union */ djvu_text_page_union (union_box, &box); } else { /* A new line, a new box */ page->results = g_list_prepend (page->results, ev_rectangle_copy (&box)); } } if (p == page->end) return FALSE; } return TRUE; }
static jboolean miniexp_get_text(JNIEnv * env, miniexp_t exp, jobject stringBuilder, jobject positions, int *state, jclass rectFClass, jmethodID ctor, jmethodID addToList, int pageHeight) { miniexp_t type = miniexp_car(exp); int typenum = parse_text_type(type); miniexp_t r = exp = miniexp_cdr(exp); if (! miniexp_symbolp(type)) return 0; jobject rect = miniexp_get_rect(&r, env, rectFClass, ctor, pageHeight); if (rect == NULL) return 0; miniexp_t s = miniexp_car(r); *state = qMax(*state, typenum); jstring space = (*env)->NewStringUTF(env, " "); jstring newLine = (*env)->NewStringUTF(env, "\n"); if (miniexp_stringp(s) && !miniexp_cdr(r)) { //result += (state >= 2) ? "\n" : (state >= 1) ? " " : ""; if (*state >= 2) { (*env)->CallBooleanMethod(env, positions, addToList, rect); (*env)->CallBooleanMethod(env, stringBuilder, addToList, newLine); } else if (*state >= 1) { (*env)->CallBooleanMethod(env, positions, addToList, rect); (*env)->CallBooleanMethod(env, stringBuilder, addToList, newLine); } else { //add empty? } *state = -1; (*env)->CallBooleanMethod(env, positions, addToList, rect); jstring string = (*env)->NewStringUTF(env, miniexp_to_str(s)); (*env)->CallBooleanMethod(env, stringBuilder, addToList, string); (*env)->DeleteLocalRef(env, string); r = miniexp_cdr(r); } (*env)->DeleteLocalRef(env, space); (*env)->DeleteLocalRef(env, newLine); (*env)->DeleteLocalRef(env, rect); while(miniexp_consp(s)) { miniexp_get_text(env, s, stringBuilder, positions, state, rectFClass, ctor, addToList, pageHeight); r = miniexp_cdr(r); s = miniexp_car(r); } if (r) return 0; *state = qMax(*state, typenum); return 1; }
//sumatrapdf code int extractText(miniexp_t item, Arraylist list, fz_bbox * target) { miniexp_t type = miniexp_car(item); if (!miniexp_symbolp(type)) return 0; item = miniexp_cdr(item); if (!miniexp_numberp(miniexp_car(item))) return 0; int x0 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item); if (!miniexp_numberp(miniexp_car(item))) return 0; int y0 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item); if (!miniexp_numberp(miniexp_car(item))) return 0; int x1 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item); if (!miniexp_numberp(miniexp_car(item))) return 0; int y1 = miniexp_to_int(miniexp_car(item)); item = miniexp_cdr(item); //RectI rect = RectI::FromXY(x0, y0, x1, y1); fz_bbox rect = {x0 , y0 , x1 , y1}; miniexp_t str = miniexp_car(item); if (miniexp_stringp(str) && !miniexp_cdr(item)) { fz_bbox inters = fz_intersect_bbox(rect, *target); //LOGI("Start text extraction: rectangle=[%d,%d,%d,%d] %s", rect.x0, rect.y0, rect.x1, rect.y1, content); if (!fz_is_empty_bbox(inters)) { const char *content = miniexp_to_str(str); while (*content) { arraylist_add(list, *content++); } // if (value) { // size_t len = str::Len(value); // // TODO: split the rectangle into individual parts per glyph // for (size_t i = 0; i < len; i++) // coords.Append(RectI(rect.x, rect.y, rect.dx, rect.dy)); // extracted.AppendAndFree(value); // } if (miniexp_symbol("word") == type) { arraylist_add(list, ' '); //coords.Append(RectI(rect.x + rect.dx, rect.y, 2, rect.dy)); } else if (miniexp_symbol("char") != type) { arraylist_add(list, '\n'); // extracted.Append(lineSep); // for (size_t i = 0; i < str::Len(lineSep); i++) // coords.Append(RectI()); } } item = miniexp_cdr(item); } while (miniexp_consp(str)) { extractText(str, list, target); item = miniexp_cdr(item); str = miniexp_car(item); } return !item; }
static gboolean string_from_miniexp(miniexp_t sexp, const char **str) { if (miniexp_stringp (sexp)) { *str = miniexp_to_str (sexp); return TRUE; } else { return FALSE; } }
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); }
int buildTOC(miniexp_t expr, list * myList, int level, JNIEnv * env, jclass olClass, jmethodID ctor) { while(miniexp_consp(expr)) { miniexp_t s = miniexp_car(expr); expr = miniexp_cdr(expr); if (miniexp_consp(s) && miniexp_consp(miniexp_cdr(s)) && miniexp_stringp(miniexp_car(s)) && miniexp_stringp(miniexp_cadr(s)) ) { // fill item const char *name = miniexp_to_str(miniexp_car(s)); const char *page = miniexp_to_str(miniexp_cadr(s)); //starts with # int pageno = -1; if (page[0] == '#') { pageno = ddjvu_document_search_pageno(doc, &page[1]); } if (pageno < 0) { LOGI("Page %s", page); } if (name == NULL) {return -1;} OutlineItem * element = (OutlineItem *) malloc(sizeof(OutlineItem)); element->title = name; element->page = pageno; element->level = level; list_item * next = (list_item *) malloc(sizeof(list_item)); next->item = element; next->next = NULL; myList->tail->next = next; myList->tail = next; // recursion buildTOC(miniexp_cddr(s), myList, level+1, env, olClass, ctor); } } return 0; }
void QDjViewOutline::fillItems(QTreeWidgetItem *root, miniexp_t expr) { while(miniexp_consp(expr)) { miniexp_t s = miniexp_car(expr); expr = miniexp_cdr(expr); if (miniexp_consp(s) && miniexp_consp(miniexp_cdr(s)) && miniexp_stringp(miniexp_car(s)) && miniexp_stringp(miniexp_cadr(s)) ) { // fill item const char *name = miniexp_to_str(miniexp_car(s)); const char *link = miniexp_to_str(miniexp_cadr(s)); int pageno = pageNumber(link); QString pagename = (pageno>=0)?djview->pageName(pageno):QString(); QTreeWidgetItem *item = new QTreeWidgetItem(root); QString text = QString::fromUtf8(name); if (name && name[0]) item->setText(0, text.replace(spaces," ")); else if (! pagename.isEmpty()) item->setText(0, tr("Page %1").arg(pagename)); item->setFlags(0); item->setWhatsThis(0, whatsThis()); if (link && link[0]) { QString slink = QString::fromUtf8(link); item->setData(0, Qt::UserRole+1, slink); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item->setToolTip(0, tr("Go: %1").arg(slink)); if (pageno >= 0) item->setData(0, Qt::UserRole, pageno); if (! pagename.isEmpty()) item->setToolTip(0, tr("Go: page %1.").arg(pagename)); } // recurse fillItems(item, miniexp_cddr(s)); } } }
extern "C" jstring Java_org_ebookdroid_droids_djvu_codec_DjvuOutline_getTitle(JNIEnv *env, jclass cls, jlong expr) { // DEBUG("DjvuOutline.getTitle(%p)",expr); miniexp_t s = miniexp_car((miniexp_t) expr); if (miniexp_consp(s) && miniexp_consp(miniexp_cdr(s)) && miniexp_stringp(miniexp_car(s)) && miniexp_stringp(miniexp_cadr(s))) { const char* buf = miniexp_to_str(miniexp_car(s)); return env->NewStringUTF(buf); } return NULL; }
static bool exp_to_str(miniexp_t expression, const char** string) { if (string == NULL) { return false; } if (miniexp_stringp(expression)) { *string = miniexp_to_str(expression); return true; } return false; }
/** * djvu_text_page_append_search: * @page: #DjvuTextPage instance * @p: tree to append * @case_sensitive: do not ignore case * @delimit: insert spaces because of higher (sentence/paragraph/...) break * * Appends the tree in @p to the internal text string. */ static void djvu_text_page_append_text (DjvuTextPage *page, miniexp_t p, gboolean case_sensitive, gboolean delimit) { char *token_text; miniexp_t deeper; g_return_if_fail (miniexp_consp (p) && miniexp_symbolp (miniexp_car (p))); delimit |= page->char_symbol != miniexp_car (p); deeper = miniexp_cddr (miniexp_cdddr (p)); while (deeper != miniexp_nil) { miniexp_t data = miniexp_car (deeper); if (miniexp_stringp (data)) { DjvuTextLink link; link.position = page->text == NULL ? 0 : strlen (page->text); link.pair = p; g_array_append_val (page->links, link); token_text = (char *) miniexp_to_str (data); if (!case_sensitive) token_text = g_utf8_casefold (token_text, -1); if (page->text == NULL) page->text = g_strdup (token_text); else { char *new_text = g_strjoin (delimit ? " " : NULL, page->text, token_text, NULL); g_free (page->text); page->text = new_text; } if (!case_sensitive) g_free (token_text); } else djvu_text_page_append_text (page, data, case_sensitive, delimit); delimit = FALSE; deeper = miniexp_cdr (deeper); } }
void guFolderInspector::extractIsbnsFromDjvu(QString fileName, QList<QString> &ISBNList) { ctx = ddjvu_context_create("lgUploader"); //ddjvu_document_create_by_filename doc = ddjvu_document_create_by_filename_utf8(ctx, fileName.toUtf8(), 1); while (! ddjvu_document_decoding_done(doc)); int numOfPages = ddjvu_document_get_pagenum(doc); //количество страниц - строго! //QByteArray b = QFile::encodeName(fileName); //doc = ddjvu_document_create_by_filename(ctx, b, 1); if(!doc) qDebug() << "error create doc"; if(!ctx) qDebug() << "error create context"; const char *lvl = "page"; //начало перебора по страницам isbnMethods find; int numOfSearchPages = 15; //qDebug() << "num of pages " << numOfPages; if(numOfPages < numOfSearchPages) { numOfSearchPages = numOfPages; } for (int pageCount = 0 ; pageCount < numOfSearchPages ; pageCount++) { miniexp_t r = miniexp_nil; while ((r = ddjvu_document_get_pagetext(doc, pageCount ,lvl))==miniexp_dummy); r = miniexp_nth(5, r); //if ( r == miniexp_nil ) // qDebug() << "r = null"; const char *pageDumpArr = miniexp_to_str( r ); QString pageDump( QString::fromUtf8( pageDumpArr )); find.findIsbns(pageDump, ISBNList); //qDebug() << fileName << " content: \n" << pageDump ; } //конец перебора по страницам if (doc) ddjvu_document_release(doc); //освобождаем контекст документа if (ctx) ddjvu_context_release(ctx); //освобождаем контескт приложени¤ (возможно стоит оставить) }
static void djvu_text_page_limits_process (DjvuTextPage *page, miniexp_t p, EvRectangle *rect) { EvRectangle current; const char *text; current.x1 = miniexp_to_int (miniexp_nth (1, p)); current.y1 = miniexp_to_int (miniexp_nth (2, p)); current.x2 = miniexp_to_int (miniexp_nth (3, p)); current.y2 = miniexp_to_int (miniexp_nth (4, p)); text = miniexp_to_str (miniexp_nth (5, p)); if (current.x2 >= rect->x1 && current.y1 <= rect->y2 && current.x1 <= rect->x2 && current.y2 >= rect->y1 && text != NULL && text[0] != '\0') { if (page->start == miniexp_nil) page->start = p; page->end = p; } }
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(); }
/** * djvu_text_page_selection_process: * @page: #DjvuTextPage instance * @p: s-expression to append * @delimit: character/word/... delimiter * * Appends the string in @p to the page text. * * Returns: whether the end was not reached in this s-expression */ static gboolean djvu_text_page_selection_process (DjvuTextPage *page, miniexp_t p, int delimit) { if (page->text || p == page->start) { char *token_text = (char *) miniexp_to_str (miniexp_nth (5, p)); if (page->text) { char *new_text = g_strjoin (delimit & 2 ? "\n" : delimit & 1 ? " " : NULL, page->text, token_text, NULL); g_free (page->text); page->text = new_text; } else page->text = g_strdup (token_text); if (p == page->end) return FALSE; } return TRUE; }
void dopage(int pageno) { miniexp_t r = miniexp_nil; const char *lvl = (detail) ? detail : "page"; while ((r = ddjvu_document_get_pagetext(doc,pageno-1,lvl))==miniexp_dummy) handle(TRUE); if (detail) { miniexp_io_t io; miniexp_io_init(&io); io.p_print7bits = &escape; miniexp_pprint_r(&io, r, 72); } else if ((r = miniexp_nth(5, r)) && miniexp_stringp(r)) { const char *s = miniexp_to_str(r); if (! escape) fputs(s, stdout); else { unsigned char c; while ((c = *(unsigned char*)s++)) { bool esc = false; if (c == '\\' || c >= 0x7f) esc = true; /* non-ascii */ if (c < 0x20 && !strchr("\013\035\037\012", c)) esc = true; /* non-printable other than separators */ if (esc) printf("\\%03o", c); else putc(c, stdout); } } fputs("\n\f", stdout); } }
extern "C" jstring Java_org_ebookdroid_droids_djvu_codec_DjvuOutline_getLink(JNIEnv *env, jclass cls, jlong expr, jlong docHandle) { // DEBUG("DjvuOutline.getLinkPage(%p)",expr); miniexp_t s = miniexp_car((miniexp_t) expr); if (miniexp_consp(s) && miniexp_consp(miniexp_cdr(s)) && miniexp_stringp(miniexp_car(s)) && miniexp_stringp(miniexp_cadr(s))) { const char *link = miniexp_to_str(miniexp_cadr(s)); int number = -1; if (link && link[0] == '#') { number = ddjvu_document_search_pageno((ddjvu_document_t*) docHandle, link + 1); if (number >= 0) { char linkbuf[128]; snprintf(linkbuf, 127, "#%d", number + 1); return env->NewStringUTF(linkbuf); } } return env->NewStringUTF(link); } return NULL; }
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; }
static void build_index(djvu_document_t *djvu_document, miniexp_t expression, girara_tree_node_t* root) { if (expression == miniexp_nil || root == NULL) { return; } int fileno = ddjvu_document_get_filenum(djvu_document->document); int curfile = 0; while (miniexp_consp(expression) != 0) { miniexp_t inner = miniexp_car(expression); if (miniexp_consp(inner) && miniexp_consp(miniexp_cdr(inner)) && miniexp_stringp(miniexp_car(inner)) && miniexp_stringp(miniexp_car(inner)) ) { const char* name = miniexp_to_str(miniexp_car(inner)); const char* link = miniexp_to_str(miniexp_cadr(inner)); /* TODO: handle other links? */ if (link == NULL || link[0] != '#') { expression = miniexp_cdr(expression); continue; } zathura_link_type_t type = ZATHURA_LINK_GOTO_DEST; zathura_rectangle_t rect; zathura_link_target_t target = { 0 }; target.destination_type = ZATHURA_LINK_DESTINATION_XYZ; /* Check if link+1 contains a number */ bool number = true; const size_t linklen = strlen(link); for (unsigned int k = 1; k < linklen; k++) { if (!isdigit(link[k])) { number = false; break; } } /* if link starts with a number assume it is a number */ if (number == true) { target.page_number = atoi(link + 1) - 1; } else { /* otherwise assume it is an id for a page */ ddjvu_fileinfo_t info; int f, i; for (i=0; i < fileno; i++) { f = (curfile + i) % fileno; ddjvu_document_get_fileinfo(djvu_document->document, f, &info); if (info.id != NULL && !strcmp(link+1, info.id)) { break; } } /* got a page */ if (i < fileno && info.pageno >= 0) { curfile = (f+1) % fileno; target.page_number = info.pageno; } else { /* give up */ expression = miniexp_cdr(expression); continue; } } zathura_index_element_t* index_element = zathura_index_element_new(name); if (index_element == NULL) { continue; } index_element->link = zathura_link_new(type, rect, target); if (index_element->link == NULL) { zathura_index_element_free(index_element); continue; } girara_tree_node_t* node = girara_node_append_data(root, index_element); /* search recursive */ build_index(djvu_document, miniexp_cddr(inner), node); } expression = miniexp_cdr(expression); } }
void djvu_get_djvu_words(SearchHelper& h, jobject list, miniexp_t expr, jstring pattern) { int coords[4]; if (!miniexp_consp(expr)) { return; } miniexp_t head = miniexp_car(expr); expr = miniexp_cdr(expr); if (!miniexp_symbolp(head)) { return; } int i; for (i = 0; i < 4 && miniexp_consp(expr); i++) { head = miniexp_car(expr); expr = miniexp_cdr(expr); if (!miniexp_numberp(head)) { return; } coords[i] = miniexp_to_int(head); } while (miniexp_consp(expr)) { head = miniexp_car(expr); if (miniexp_stringp(head)) { const char* text = miniexp_to_str(head); // DEBUG("%d, %d, %d, %d: %s", coords[0], coords[1], coords[2], coords[3], text); bool add = !pattern; jstring txt = h.str.toString(text); if (pattern) { jstring ltxt = h.str.toLowerCase(txt); add = h.str.indexOf(ltxt, pattern) >= 0; h.str.release(ltxt); } if (add) { // add to list jobject ptb = h.box.create(); h.box.setRect(ptb, coords); h.box.setText(ptb, txt); h.arr.add(list, ptb); } else { h.str.release(txt); } } else if (miniexp_consp(head)) { djvu_get_djvu_words(h, list, head, pattern); } expr = miniexp_cdr(expr); } }
/* * Return a table like following: * { * -- a line entry * 1 = { * 1 = {word="This", x0=377, y0=4857, x1=2427, y1=5089}, * 2 = {word="is", x0=377, y0=4857, x1=2427, y1=5089}, * 3 = {word="Word", x0=377, y0=4857, x1=2427, y1=5089}, * 4 = {word="List", x0=377, y0=4857, x1=2427, y1=5089}, * x0 = 377, y0 = 4857, x1 = 2427, y1 = 5089, * }, * * -- an other line entry * 2 = { * 1 = {word="This", x0=377, y0=4857, x1=2427, y1=5089}, * 2 = {word="is", x0=377, y0=4857, x1=2427, y1=5089}, * x0 = 377, y0 = 4857, x1 = 2427, y1 = 5089, * }, * } */ static int getPageText(lua_State *L) { DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument"); int pageno = luaL_checkint(L, 2); /* get page height for coordinates transform */ ddjvu_pageinfo_t info; ddjvu_status_t r; while ((r=ddjvu_document_get_pageinfo( doc->doc_ref, pageno-1, &info))<DDJVU_JOB_OK) { handle(L, doc->context, TRUE); } if (r>=DDJVU_JOB_FAILED) return luaL_error(L, "cannot get page #%d information", pageno); /* start retrieving page text */ miniexp_t sexp, se_line, se_word; int i = 1, j = 1, counter_l = 1, counter_w=1, nr_line = 0, nr_word = 0; const char *word = NULL; while ((sexp = ddjvu_document_get_pagetext(doc->doc_ref, pageno-1, "word")) == miniexp_dummy) { handle(L, doc->context, True); } /* throuw page info and obtain lines info, after this, sexp's entries * are lines. */ sexp = miniexp_cdr(sexp); /* get number of lines in a page */ nr_line = miniexp_length(sexp); /* table that contains all the lines */ lua_newtable(L); counter_l = 1; for(i = 1; i <= nr_line; i++) { /* retrive one line entry */ se_line = miniexp_nth(i, sexp); nr_word = miniexp_length(se_line); if (nr_word == 0) { continue; } /* subtable that contains words in a line */ lua_pushnumber(L, counter_l); lua_newtable(L); counter_l++; /* set line position */ lua_pushstring(L, "x0"); lua_pushnumber(L, miniexp_to_int(miniexp_nth(1, se_line))); lua_settable(L, -3); lua_pushstring(L, "y1"); lua_pushnumber(L, info.height - miniexp_to_int(miniexp_nth(2, se_line))); lua_settable(L, -3); lua_pushstring(L, "x1"); lua_pushnumber(L, miniexp_to_int(miniexp_nth(3, se_line))); lua_settable(L, -3); lua_pushstring(L, "y0"); lua_pushnumber(L, info.height - miniexp_to_int(miniexp_nth(4, se_line))); lua_settable(L, -3); /* now loop through each word in the line */ counter_w = 1; for(j = 1; j <= nr_word; j++) { /* retrive one word entry */ se_word = miniexp_nth(j, se_line); /* check to see whether the entry is empty */ word = miniexp_to_str(miniexp_nth(5, se_word)); if (!word) { continue; } /* create table that contains info for a word */ lua_pushnumber(L, counter_w); lua_newtable(L); counter_w++; /* set word info */ lua_pushstring(L, "x0"); lua_pushnumber(L, miniexp_to_int(miniexp_nth(1, se_word))); lua_settable(L, -3); lua_pushstring(L, "y1"); lua_pushnumber(L, info.height - miniexp_to_int(miniexp_nth(2, se_word))); lua_settable(L, -3); lua_pushstring(L, "x1"); lua_pushnumber(L, miniexp_to_int(miniexp_nth(3, se_word))); lua_settable(L, -3); lua_pushstring(L, "y0"); lua_pushnumber(L, info.height - miniexp_to_int(miniexp_nth(4, se_word))); lua_settable(L, -3); lua_pushstring(L, "word"); lua_pushstring(L, word); lua_settable(L, -3); /* set word entry to line subtable */ lua_settable(L, -3); } /* end of for (j) */ /* set line entry to page text table */ lua_settable(L, -3); } /* end of for (i) */ return 1; }