jobject djvu_links_get_links(JNIEnv *jenv, ddjvu_document_t* djvu_document, int page) { DEBUG("djvu_links_get_links %d", page); miniexp_t page_annotations = miniexp_nil; miniexp_t *hyperlinks = NULL, *iter = NULL; ddjvu_pageinfo_t page_info; jobject arrayList = NULL; page_annotations = ddjvu_document_get_pageanno(djvu_document, page); ddjvu_document_get_pageinfo(djvu_document, page, &page_info); if (page_annotations) { hyperlinks = ddjvu_anno_get_hyperlinks(page_annotations); if (hyperlinks) { jclass arrayListClass = jenv->FindClass("java/util/ArrayList"); if (!arrayListClass) return arrayList; jmethodID alInitMethodId = jenv->GetMethodID(arrayListClass, "<init>", "()V"); if (!alInitMethodId) return arrayList; jmethodID alAddMethodId = jenv->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); if (!alAddMethodId) return arrayList; arrayList = jenv->NewObject(arrayListClass, alInitMethodId); if (!arrayList) return arrayList; for (iter = hyperlinks; *iter; ++iter) { jobject hl = get_djvu_hyperlink_mapping(jenv, djvu_document, &page_info, *iter); if (hl) jenv->CallBooleanMethod(arrayList, alAddMethodId, hl); //jenv->DeleteLocalRef(hl); } free(hyperlinks); } ddjvu_miniexp_release(djvu_document, page_annotations); } return arrayList; }
EvMappingList * djvu_links_get_links (EvDocumentLinks *document_links, gint page, double scale_factor) { DjvuDocument *djvu_document = DJVU_DOCUMENT (document_links); GList *retval = NULL; miniexp_t page_annotations = miniexp_nil; miniexp_t *hyperlinks = NULL, *iter = NULL; EvMapping *ev_link_mapping; ddjvu_pageinfo_t page_info; while ((page_annotations = ddjvu_document_get_pageanno (djvu_document->d_document, page)) == miniexp_dummy) djvu_handle_events (djvu_document, TRUE, NULL); while (ddjvu_document_get_pageinfo (djvu_document->d_document, page, &page_info) < DDJVU_JOB_OK) djvu_handle_events(djvu_document, TRUE, NULL); if (page_annotations) { hyperlinks = ddjvu_anno_get_hyperlinks (page_annotations); if (hyperlinks) { for (iter = hyperlinks; *iter; ++iter) { ev_link_mapping = get_djvu_hyperlink_mapping (djvu_document, page, &page_info, *iter); if (ev_link_mapping) { ev_link_mapping->area.x1 *= scale_factor; ev_link_mapping->area.x2 *= scale_factor; ev_link_mapping->area.y1 *= scale_factor; ev_link_mapping->area.y2 *= scale_factor; retval = g_list_prepend (retval, ev_link_mapping); } } free (hyperlinks); } ddjvu_miniexp_release (djvu_document->d_document, page_annotations); } return ev_mapping_list_new (page, retval, (GDestroyNotify)g_object_unref); }
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; }
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; }