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; }
/** * djvu_text_page_sexpr: * @page: #DjvuTextPage instance * @p: tree to append * @start: first s-expression in the selection * @end: last s-expression in the selection * * Walks the tree in @p and extends the rectangle with * djvu_text_page_process() for all s-expressions between @start and @end. * * Returns: whether the end was not reached in this subtree */ static gboolean djvu_text_page_sexpr (DjvuTextPage *page, miniexp_t p, miniexp_t start, miniexp_t end) { g_return_val_if_fail (miniexp_consp (p) && miniexp_symbolp (miniexp_car (p)), FALSE); miniexp_t deeper = miniexp_cddr (miniexp_cdddr (p)); while (deeper != miniexp_nil) { miniexp_t str = miniexp_car (deeper); if (miniexp_stringp (str)) { if (!djvu_text_page_sexpr_process (page, p, start, end)) return FALSE; } else { if (!djvu_text_page_sexpr (page, str, start, end)) return FALSE; } deeper = miniexp_cdr (deeper); } return TRUE; }
/** * djvu_text_page_selection: * @page: #DjvuTextPage instance * @p: tree to append * @delimit: character/word/... delimiter * * Walks the tree in @p and appends the text with * djvu_text_page_selection_process() for all s-expressions * between the start and end fields. * * Returns: whether the end was not reached in this subtree */ static gboolean djvu_text_page_selection (DjvuTextPage *page, miniexp_t p, int delimit) { g_return_val_if_fail (miniexp_consp (p) && miniexp_symbolp (miniexp_car (p)), FALSE); if (miniexp_car (p) != page->char_symbol) delimit |= miniexp_car (p) == page->word_symbol ? 1 : 2; miniexp_t deeper = miniexp_cddr (miniexp_cdddr (p)); while (deeper != miniexp_nil) { miniexp_t str = miniexp_car (deeper); if (miniexp_stringp (str)) { if (!djvu_text_page_selection_process (page, p, delimit)) return FALSE; } else { if (!djvu_text_page_selection (page, str, delimit)) return FALSE; } delimit = 0; deeper = miniexp_cdr (deeper); } return TRUE; }
extern "C" jlong Java_org_ebookdroid_droids_djvu_codec_DjvuOutline_getChild(JNIEnv *env, jclass cls, jlong expr) { // DEBUG("DjvuOutline.getChild(%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))) return (jlong) miniexp_cddr(s); return 0; }
static int miniexp_get_int(miniexp_t * r, int * x) { if (! miniexp_numberp(miniexp_car(*r))) return 0; *x = miniexp_to_int(miniexp_car(*r)); *r = miniexp_cdr(*r); return 1; }
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; }
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; }
void declare(llvm::Module* module, minivar_t declare_list) { minivar_t name = miniexp_car(declare_list); minivar_t object = miniexp_cadr(declare_list); minivar_t objecttype = miniexp_car(object); if(miniexp_to_stdname(objecttype) == "fun") { declare_fun(module, name, miniexp_cadr(declare_list)); } else { std::cerr << "Unknown object type " << miniexp_to_stdname(objecttype) << " to declare " << miniexp_to_stdname(name) << std::endl; return; } }
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; }
girara_tree_node_t* djvu_document_index_generate(zathura_document_t* document, djvu_document_t* djvu_document, zathura_error_t* error) { if (document == NULL || djvu_document == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_INVALID_ARGUMENTS; } return NULL; } miniexp_t outline = miniexp_dummy; while ((outline = ddjvu_document_get_outline(djvu_document->document)) == miniexp_dummy) { handle_messages(djvu_document, true); } if (outline == miniexp_dummy) { return NULL; } if (miniexp_consp(outline) == 0 || miniexp_car(outline) != miniexp_symbol("bookmarks")) { ddjvu_miniexp_release(djvu_document->document, outline); return NULL; } girara_tree_node_t* root = girara_node_new(zathura_index_element_new("ROOT")); build_index(djvu_document, miniexp_cdr(outline), root); ddjvu_miniexp_release(djvu_document->document, outline); return root; }
/** * 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); } }
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; }
static void djvu_text_page_limits (DjvuTextPage *page, miniexp_t p, EvRectangle *rect) { g_return_if_fail (miniexp_consp (p) && miniexp_symbolp (miniexp_car (p))); miniexp_t deeper = miniexp_cddr (miniexp_cdddr (p)); while (deeper != miniexp_nil) { miniexp_t str = miniexp_car (deeper); if (miniexp_stringp (str)) djvu_text_page_limits_process (page, p, rect); else djvu_text_page_limits (page, str, rect); deeper = miniexp_cdr (deeper); } }
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)); } } }
void QDjViewOutline::refresh() { QDjVuDocument *doc = djview->getDocument(); if (doc && !loaded && djview->pageNum()>0) { miniexp_t outline = doc->getDocumentOutline(); if (outline == miniexp_dummy) return; loaded = true; if (outline) { if (!miniexp_consp(outline) || miniexp_car(outline) != miniexp_symbol("bookmarks")) { QString msg = tr("Outline data is corrupted"); qWarning("%s", (const char*)msg.toLocal8Bit()); } tree->clear(); QTreeWidgetItem *root = new QTreeWidgetItem(); fillItems(root, miniexp_cdr(outline)); while (root->childCount() > 0) tree->insertTopLevelItem(tree->topLevelItemCount(), root->takeChild(0) ); if (tree->topLevelItemCount() == 1) tree->topLevelItem(0)->setExpanded(true); delete root; } else { tree->clear(); QTreeWidgetItem *root = new QTreeWidgetItem(tree); root->setText(0, tr("Pages")); root->setFlags(Qt::ItemIsEnabled); root->setData(0, Qt::UserRole, -1); for (int pageno=0; pageno<djview->pageNum(); pageno++) { QTreeWidgetItem *item = new QTreeWidgetItem(root); QString name = djview->pageName(pageno); item->setText(0, tr("Page %1").arg(name)); item->setData(0, Qt::UserRole, pageno); item->setData(0, Qt::UserRole+1, pageno); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item->setToolTip(0, tr("Go: page %1.").arg(name)); item->setWhatsThis(0, whatsThis()); } tree->setItemExpanded(root, true); } pageChanged(djview->getDjVuWidget()->page()); } }
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; }
//Outline extern "C" jlong Java_org_ebookdroid_droids_djvu_codec_DjvuOutline_open(JNIEnv *env, jclass cls, jlong docHandle) { // DEBUG("DjvuOutline.open(%p)",docHandle); miniexp_t outline = ddjvu_document_get_outline((ddjvu_document_t*) docHandle); if (outline && outline != miniexp_dummy) { if (!miniexp_consp(outline) || miniexp_car(outline) != miniexp_symbol("bookmarks")) { ERROR("%s", "Outline data is corrupted"); return 0; } else return (jlong) outline; // debug_outline(outline); } return 0; }
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; }
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; }
/** * Builds the index GtkTreeModel from DjVu s-expr * * (bookmarks * ("title1" "dest1" * ("title12" "dest12" * ... ) * ... ) * ("title2" "dest2" * ... ) * ... ) */ static void build_tree (const DjvuDocument *djvu_document, GtkTreeModel *model, GtkTreeIter *parent, miniexp_t iter) { const char *title, *link_dest; char *title_markup; EvLinkAction *ev_action = NULL; EvLink *ev_link = NULL; GtkTreeIter tree_iter; if (miniexp_car (iter) == miniexp_symbol ("bookmarks")) { /* The (bookmarks) cons */ iter = miniexp_cdr (iter); } else if ( miniexp_length (iter) >= 2 ) { gchar *utf8_title = NULL; /* An entry */ if (!string_from_miniexp (miniexp_car (iter), &title)) goto unknown_entry; if (!string_from_miniexp (miniexp_cadr (iter), &link_dest)) goto unknown_entry; if (!g_utf8_validate (title, -1, NULL)) { utf8_title = str_to_utf8 (title); title_markup = g_markup_escape_text (utf8_title, -1); } else { title_markup = g_markup_escape_text (title, -1); } ev_action = get_djvu_link_action (djvu_document, link_dest, -1); if (ev_action) { ev_link = ev_link_new (utf8_title ? utf8_title : title, ev_action); gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent); gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter, EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup, EV_DOCUMENT_LINKS_COLUMN_LINK, ev_link, EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE, -1); g_object_unref (ev_action); g_object_unref (ev_link); } else { gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent); gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter, EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup, EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE, -1); } g_free (title_markup); g_free (utf8_title); iter = miniexp_cddr (iter); parent = &tree_iter; } else { goto unknown_entry; } for (; iter != miniexp_nil; iter = miniexp_cdr (iter)) { build_tree (djvu_document, model, parent, miniexp_car (iter)); } return; unknown_entry: g_warning ("DjvuLibre error: Unknown entry in bookmarks"); return; }
girara_list_t* djvu_page_links_get(zathura_page_t* page, void* UNUSED(data), zathura_error_t* error) { if (page == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_INVALID_ARGUMENTS; } goto error_ret; } zathura_document_t* document = zathura_page_get_document(page); if (document == NULL) { goto error_ret; } girara_list_t* list = girara_list_new2((girara_free_function_t) zathura_link_free); if (list == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_OUT_OF_MEMORY; } goto error_ret; } djvu_document_t* djvu_document = zathura_document_get_data(document); miniexp_t annotations = miniexp_nil; while ((annotations = ddjvu_document_get_pageanno(djvu_document->document, zathura_page_get_index(page))) == miniexp_dummy) { handle_messages(djvu_document, true); } if (annotations == miniexp_nil) { goto error_free; } miniexp_t* hyperlinks = ddjvu_anno_get_hyperlinks(annotations); for (miniexp_t* iter = hyperlinks; *iter != NULL; iter++) { if (miniexp_car(*iter) != miniexp_symbol("maparea")) { continue; } miniexp_t inner = miniexp_cdr(*iter); /* extract url information */ const char* target_string = NULL; if (miniexp_caar(inner) == miniexp_symbol("url")) { if (exp_to_str(miniexp_caddr(miniexp_car(inner)), &target_string) == false) { continue; } } else { if (exp_to_str(miniexp_car(inner), &target_string) == false) { continue; } } /* skip comment */ inner = miniexp_cdr(inner); /* extract link area */ inner = miniexp_cdr(inner); zathura_rectangle_t rect = { 0, 0, 0, 0 }; if (exp_to_rect(miniexp_car(inner), &rect) == false) { continue; } /* update rect */ unsigned int page_height = zathura_page_get_height(page) / ZATHURA_DJVU_SCALE; rect.x1 = rect.x1 * ZATHURA_DJVU_SCALE; rect.x2 = rect.x2 * ZATHURA_DJVU_SCALE; double tmp = rect.y1; rect.y1 = (page_height - rect.y2) * ZATHURA_DJVU_SCALE; rect.y2 = (page_height - tmp) * ZATHURA_DJVU_SCALE; /* create zathura link */ zathura_link_type_t type = ZATHURA_LINK_INVALID; zathura_link_target_t target = { ZATHURA_LINK_DESTINATION_UNKNOWN, NULL, 0, -1, -1, -1, -1, 0 };; /* goto page */ if (target_string[0] == '#' && target_string[1] == 'p') { type = ZATHURA_LINK_GOTO_DEST; target.page_number = atoi(target_string + 2) - 1; /* url or other? */ } else if (strstr(target_string, "//") != NULL) { type = ZATHURA_LINK_URI; target.value = (char*) target_string; /* TODO: Parse all different links */ } else { continue; } zathura_link_t* link = zathura_link_new(type, rect, target); if (link != NULL) { girara_list_append(list, link); } } return list; error_free: if (list != NULL) { girara_list_free(list); } error_ret: return NULL; }
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); } }
static bool exp_to_rect(miniexp_t expression, zathura_rectangle_t* rect) { if ((miniexp_car(expression) == miniexp_symbol("rect") || miniexp_car(expression) == miniexp_symbol("oval")) && miniexp_length(expression) == 5) { int min_x = 0; int min_y = 0; int width = 0; int height = 0; miniexp_t iter = miniexp_cdr(expression); if (exp_to_int(miniexp_car(iter), &min_x) == false) { return false; } iter = miniexp_cdr(iter); if (exp_to_int(miniexp_car(iter), &min_y) == false) { return false; } iter = miniexp_cdr(iter); if (exp_to_int(miniexp_car(iter), &width) == false) { return false; } iter = miniexp_cdr(iter); if (exp_to_int(miniexp_car(iter), &height) == false) { return false; } rect->x1 = min_x; rect->x2 = min_x + width; rect->y1 = min_y; rect->y2 = min_y + height; } else if (miniexp_car(expression) == miniexp_symbol("poly") && miniexp_length(expression) >= 5) { int min_x = 0; int min_y = 0; int max_x = 0; int max_y = 0; miniexp_t iter = miniexp_cdr(expression); while (iter != miniexp_nil) { int x = 0; int y = 0; if (exp_to_int(miniexp_car(iter), &x) == false) { return false; } iter = miniexp_cdr(iter); if (exp_to_int(miniexp_car(iter), &y) == false) { return false; } iter = miniexp_cdr(iter); min_x = MIN(min_x, x); min_y = MIN(min_y, y); max_x = MAX(max_x, x); max_y = MAX(max_y, y); } rect->x1 = min_x; rect->x2 = max_x; rect->y1 = min_y; rect->y2 = max_y; } return true; }
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); } }
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; }
JNIEXPORT jobjectArray JNICALL Java_universe_constellation_orion_viewer_djvu_DjvuDocument_getOutline(JNIEnv * env, jobject thiz) { miniexp_t outline = ddjvu_document_get_outline(doc); if (outline == miniexp_dummy || outline == NULL) { return NULL; } if (!miniexp_consp(outline) || miniexp_car(outline) != miniexp_symbol("bookmarks")) { LOGI("Outlines is empty"); } list_item * root = (list_item *) malloc(sizeof(list_item)); root->next = NULL; list * myList = (list *) malloc(sizeof(list)); myList->head = root; myList->tail = root; jclass olClass; jmethodID ctor; olClass = (*env)->FindClass(env, "universe/constellation/orion/viewer/outline/OutlineItem"); if (olClass == NULL) return NULL; ctor = (*env)->GetMethodID(env, olClass, "<init>", "(ILjava/lang/String;I)V"); if (ctor == NULL) return NULL; buildTOC(miniexp_cdr(outline), myList, 0, env, olClass, ctor); list_item * next = myList->head; int size = 0; while (next->next != NULL) { next = next->next; size++; } LOGI("Outline has %i entries", size); jobjectArray arr = (*env)->NewObjectArray(env, size, olClass, NULL); if (arr == NULL) { return NULL; } next = root->next; int pos = 0; while (next != NULL) { OutlineItem * item = next->item; jstring title = (*env)->NewStringUTF(env, item->title); //shift pageno to zero based jobject element = (*env)->NewObject(env, olClass, ctor, item->level, title, item->page - 1); (*env)->SetObjectArrayElement(env, arr, pos, element); (*env)->DeleteLocalRef(env, title); (*env)->DeleteLocalRef(env, element); free(item); list_item * next2 = next->next; free(next); next = next2; pos++; } free(root); return arr; }
//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; }