diff options
-rw-r--r-- | include/mupdf/fitz/document.h | 9 | ||||
-rw-r--r-- | include/mupdf/fitz/link.h | 145 | ||||
-rw-r--r-- | include/mupdf/fitz/outline.h | 12 | ||||
-rw-r--r-- | include/mupdf/pdf/annot.h | 7 | ||||
-rw-r--r-- | platform/android/viewer/jni/mupdf.c | 62 | ||||
-rw-r--r-- | platform/gl/gl-main.c | 17 | ||||
-rw-r--r-- | platform/ios/Classes/MuDocumentController.m | 13 | ||||
-rw-r--r-- | platform/ios/Classes/MuHitView.m | 11 | ||||
-rw-r--r-- | platform/java/mupdf_native.c | 22 | ||||
-rw-r--r-- | platform/x11/pdfapp.c | 8 | ||||
-rw-r--r-- | source/fitz/document.c | 9 | ||||
-rw-r--r-- | source/fitz/link.c | 58 | ||||
-rw-r--r-- | source/fitz/outline.c | 6 | ||||
-rw-r--r-- | source/html/epub-doc.c | 48 | ||||
-rw-r--r-- | source/html/html-layout.c | 14 | ||||
-rw-r--r-- | source/pdf/pdf-annot.c | 272 | ||||
-rw-r--r-- | source/pdf/pdf-outline.c | 8 | ||||
-rw-r--r-- | source/pdf/pdf-page.c | 6 | ||||
-rw-r--r-- | source/pdf/pdf-xref.c | 1 | ||||
-rw-r--r-- | source/tools/murun.c | 29 | ||||
-rw-r--r-- | source/xps/xps-link.c | 18 | ||||
-rw-r--r-- | source/xps/xps-outline.c | 5 | ||||
-rw-r--r-- | source/xps/xps-zip.c | 1 |
23 files changed, 248 insertions, 533 deletions
diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h index 7f3c8ece..d8123a00 100644 --- a/include/mupdf/fitz/document.h +++ b/include/mupdf/fitz/document.h @@ -32,6 +32,7 @@ typedef int (fz_document_authenticate_password_fn)(fz_context *ctx, fz_document typedef int (fz_document_has_permission_fn)(fz_context *ctx, fz_document *doc, fz_permission permission); typedef fz_outline *(fz_document_load_outline_fn)(fz_context *ctx, fz_document *doc); typedef void (fz_document_layout_fn)(fz_context *ctx, fz_document *doc, float w, float h, float em); +typedef int (fz_document_resolve_link_fn)(fz_context *ctx, fz_document *doc, const char *uri); typedef int (fz_document_count_pages_fn)(fz_context *ctx, fz_document *doc); typedef fz_page *(fz_document_load_page_fn)(fz_context *ctx, fz_document *doc, int number); typedef int (fz_document_lookup_metadata_fn)(fz_context *ctx, fz_document *doc, const char *key, char *buf, int size); @@ -87,6 +88,7 @@ struct fz_document_s fz_document_has_permission_fn *has_permission; fz_document_load_outline_fn *load_outline; fz_document_layout_fn *layout; + fz_document_resolve_link_fn *resolve_link; fz_document_count_pages_fn *count_pages; fz_document_load_page_fn *load_page; fz_document_lookup_metadata_fn *lookup_metadata; @@ -210,6 +212,13 @@ void fz_layout_document(fz_context *ctx, fz_document *doc, float w, float h, flo int fz_count_pages(fz_context *ctx, fz_document *doc); /* + fz_resolve_link: Resolve an internal link to a page number. + + Returns -1 if the URI cannot be resolved. +*/ +int fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri); + +/* fz_load_page: Load a page. After fz_load_page is it possible to retrieve the size of the diff --git a/include/mupdf/fitz/link.h b/include/mupdf/fitz/link.h index 47abe1b4..e00d66d4 100644 --- a/include/mupdf/fitz/link.h +++ b/include/mupdf/fitz/link.h @@ -7,135 +7,10 @@ /* Links - - NOTE: The link destination struct is scheduled for imminent change! - Use at your own peril. */ typedef struct fz_link_s fz_link; -typedef struct fz_link_dest_s fz_link_dest; - -typedef enum fz_link_kind_e -{ - FZ_LINK_NONE = 0, - FZ_LINK_GOTO, - FZ_LINK_URI, - FZ_LINK_LAUNCH, - FZ_LINK_NAMED, - FZ_LINK_GOTOR -} fz_link_kind; - -enum { - fz_link_flag_l_valid = 1, /* lt.x is valid */ - fz_link_flag_t_valid = 2, /* lt.y is valid */ - fz_link_flag_r_valid = 4, /* rb.x is valid */ - fz_link_flag_b_valid = 8, /* rb.y is valid */ - fz_link_flag_fit_h = 16, /* Fit horizontally */ - fz_link_flag_fit_v = 32, /* Fit vertically */ - fz_link_flag_r_is_zoom = 64 /* rb.x is actually a zoom figure */ -}; - -/* - fz_link_dest: This structure represents the destination of - an fz_link; this may be a page to display, a new file to open, - a javascript action to perform, etc. - - kind: This identifies the kind of link destination. Different - kinds use different sections of the union. - - For FZ_LINK_GOTO or FZ_LINK_GOTOR: - - gotor.page: The target page number to move to (0 being the - first page in the document). In the FZ_LINK_GOTOR case, the - page number either refers to to the file specified by - gotor.file_spec, or the page number is -1 suggesting that - the destination is given by gotor.dest. - - gotor.dest: If set, the target destination name to be - resolved in the file specified by gotor.file_spec. Always - NULL in the FZ_LINK_GOTO case. - - gotor.flags: A bitfield consisting of fz_link_flag_* - describing the validity and meaning of the different parts - of gotor.lt and gotor.rb. Link destinations are constructed - (as far as possible) so that lt and rb can be treated as a - bounding box, though the validity flags indicate which of the - values was actually specified in the file. - - gotor.lt: The top left corner of the destination bounding box. - - gotor.rb: The bottom right corner of the destination bounding - box. If fz_link_flag_r_is_zoom is set, then the r figure - should actually be interpreted as a zoom ratio. - - gotor.file_spec: If set, this destination should cause a new - file to be opened; this field holds a pointer to a remote - file specification (UTF-8). Always NULL in the FZ_LINK_GOTO - case. - - gotor.new_window: If true, the destination should open in a - new window. Always false in the FZ_LINK_GOTO case. - - For FZ_LINK_URI: - - uri.uri: A UTF-8 encoded URI to launch. - - uri.is_map: If true, the x and y coords (as ints, in user - space) should be appended to the URI before launch. - - For FZ_LINK_LAUNCH: - - launch.file_spec: A UTF-8 file specification to launch. - - launch.new_window: If true, the destination should be launched - in a new window. - - launch.is_uri: If true, launch.file_spec is a URI to launch. - - For FZ_LINK_NAMED: - - named.named: The named action to perform. Likely to be - client specific. -*/ -struct fz_link_dest_s -{ - fz_link_kind kind; - union - { - struct - { - int page; - char *dest; - int flags; - fz_point lt; - fz_point rb; - char *file_spec; - int new_window; - } - gotor; - struct - { - char *uri; - int is_map; - } - uri; - struct - { - char *file_spec; - int new_window; - int is_uri; - } - launch; - struct - { - char *named; - } - named; - } - ld; -}; - /* fz_link is a list of interactive links on a page. @@ -149,30 +24,34 @@ struct fz_link_dest_s rect: The hot zone. The area that can be clicked in untransformed coordinates. - dest: Link destinations come in two forms: Page and area that - an application should display when this link is activated. Or - as an URI that can be given to a browser. + uri: Link destinations come in two forms: internal and external. + Internal links refer to other pages in the same document. + External links are URLs to other documents. next: A pointer to the next link on the same page. */ struct fz_link_s { int refs; - fz_rect rect; - fz_link_dest dest; fz_link *next; + fz_rect rect; + void *doc; + char *uri; }; -fz_link *fz_new_link(fz_context *ctx, const fz_rect *bbox, fz_link_dest dest); +fz_link *fz_new_link(fz_context *ctx, const fz_rect *bbox, void *doc, const char *uri); fz_link *fz_keep_link(fz_context *ctx, fz_link *link); /* + Checks if a link destination is external or internal. +*/ +int fz_is_external_link(fz_context *ctx, const char *uri); + +/* fz_drop_link: Drop and free a list of links. Does not throw exceptions. */ void fz_drop_link(fz_context *ctx, fz_link *link); -void fz_drop_link_dest(fz_context *ctx, fz_link_dest *dest); - #endif diff --git a/include/mupdf/fitz/outline.h b/include/mupdf/fitz/outline.h index c3f724bc..0223ecfa 100644 --- a/include/mupdf/fitz/outline.h +++ b/include/mupdf/fitz/outline.h @@ -15,9 +15,12 @@ title: Title of outline item using UTF-8 encoding. May be NULL if the outline item has no text string. - dest: Destination in the document to be displayed when this - outline item is activated. May be FZ_LINK_NONE if the outline - item does not have a destination. + uri: Destination in the document to be displayed when this + outline item is activated. May be an internal or external + link, or NULL if the outline item does not have a destination. + + page: The page number of an internal link, or -1 for external + links or links with no destination. next: The next outline item at the same level as this outline item. May be NULL if no more outline items exist at this level. @@ -32,7 +35,8 @@ struct fz_outline_s { int refs; char *title; - fz_link_dest dest; + char *uri; + int page; fz_outline *next; fz_outline *down; int is_open; diff --git a/include/mupdf/pdf/annot.h b/include/mupdf/pdf/annot.h index 9cd80e06..caaa9047 100644 --- a/include/mupdf/pdf/annot.h +++ b/include/mupdf/pdf/annot.h @@ -101,13 +101,14 @@ struct pdf_annot_s pdf_annot *next; }; -fz_link_dest pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, fz_link_kind kind, pdf_obj *dest); -char *pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec); -fz_link_dest pdf_parse_action(fz_context *ctx, pdf_document *doc, pdf_obj *action); +char *pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec, pdf_obj *dest); +char *pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *obj); +char *pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *obj); pdf_obj *pdf_lookup_dest(fz_context *ctx, pdf_document *doc, pdf_obj *needle); pdf_obj *pdf_lookup_name(fz_context *ctx, pdf_document *doc, pdf_obj *which, pdf_obj *needle); pdf_obj *pdf_load_name_tree(fz_context *ctx, pdf_document *doc, pdf_obj *which); +int pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri); fz_link *pdf_load_link_annots(fz_context *ctx, pdf_document *, pdf_obj *annots, const fz_matrix *page_ctm); void pdf_annot_transform(fz_context *ctx, pdf_annot *annot, fz_matrix *annot_ctm); diff --git a/platform/android/viewer/jni/mupdf.c b/platform/android/viewer/jni/mupdf.c index 383228e1..ba992a43 100644 --- a/platform/android/viewer/jni/mupdf.c +++ b/platform/android/viewer/jni/mupdf.c @@ -1116,9 +1116,7 @@ countOutlineItems(fz_outline *outline) while (outline) { - if (outline->dest.kind == FZ_LINK_GOTO - && outline->dest.ld.gotor.page >= 0 - && outline->title) + if (outline->page >= 0 && outline->title) count++; count += countOutlineItems(outline->down); @@ -1133,21 +1131,18 @@ fillInOutlineItems(JNIEnv * env, jclass olClass, jmethodID ctor, jobjectArray ar { while (outline) { - if (outline->dest.kind == FZ_LINK_GOTO) + int page = outline->page; + if (page >= 0 && outline->title) { - int page = outline->dest.ld.gotor.page; - if (page >= 0 && outline->title) - { - jobject ol; - jstring title = (*env)->NewStringUTF(env, outline->title); - if (title == NULL) return -1; - ol = (*env)->NewObject(env, olClass, ctor, level, title, page); - if (ol == NULL) return -1; - (*env)->SetObjectArrayElement(env, arr, pos, ol); - (*env)->DeleteLocalRef(env, ol); - (*env)->DeleteLocalRef(env, title); - pos++; - } + jobject ol; + jstring title = (*env)->NewStringUTF(env, outline->title); + if (title == NULL) return -1; + ol = (*env)->NewObject(env, olClass, ctor, level, title, page); + if (ol == NULL) return -1; + (*env)->SetObjectArrayElement(env, arr, pos, ol); + (*env)->DeleteLocalRef(env, ol); + (*env)->DeleteLocalRef(env, title); + pos++; } pos = fillInOutlineItems(env, olClass, ctor, arr, pos, outline->down, level+1); if (pos < 0) return -1; @@ -1857,13 +1852,8 @@ JNI_FN(MuPDFCore_getPageLinksInternal)(JNIEnv * env, jobject thiz, int pageNumbe count = 0; for (link = list; link; link = link->next) { - switch (link->dest.kind) - { - case FZ_LINK_GOTO: - case FZ_LINK_GOTOR: - case FZ_LINK_URI: + if (link->uri) count++ ; - } } arr = (*env)->NewObjectArray(env, count, linkInfoClass, NULL); @@ -1879,36 +1869,18 @@ JNI_FN(MuPDFCore_getPageLinksInternal)(JNIEnv * env, jobject thiz, int pageNumbe fz_rect rect = link->rect; fz_transform_rect(&rect, &ctm); - switch (link->dest.kind) - { - case FZ_LINK_GOTO: + if (!fz_is_external_link(ctx, link->uri)) { linkInfo = (*env)->NewObject(env, linkInfoInternalClass, ctorInternal, (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1, - link->dest.ld.gotor.page); - break; - } - - case FZ_LINK_GOTOR: - { - jstring juri = (*env)->NewStringUTF(env, link->dest.ld.gotor.file_spec); - linkInfo = (*env)->NewObject(env, linkInfoRemoteClass, ctorRemote, - (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1, - juri, link->dest.ld.gotor.page, link->dest.ld.gotor.new_window ? JNI_TRUE : JNI_FALSE); - break; + fz_resolve_link(ctx, link->doc, link->uri)); } - - case FZ_LINK_URI: + else { - jstring juri = (*env)->NewStringUTF(env, link->dest.ld.uri.uri); + jstring juri = (*env)->NewStringUTF(env, link->uri); linkInfo = (*env)->NewObject(env, linkInfoExternalClass, ctorExternal, (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1, juri); - break; - } - - default: - continue; } if (linkInfo == NULL) diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c index 34d061be..9084827c 100644 --- a/platform/gl/gl-main.c +++ b/platform/gl/gl-main.c @@ -464,10 +464,9 @@ static int do_outline_imp(fz_outline *node, int end, int x0, int x1, int x, int while (node) { - if (node->dest.kind == FZ_LINK_GOTO) + p = node->page; + if (p >= 0) { - p = node->dest.ld.gotor.page; - if (ui.x >= x0 && ui.x < x1 && ui.y >= y + h && ui.y < y + h + ui.lineheight) { ui.hot = node; @@ -480,9 +479,9 @@ static int do_outline_imp(fz_outline *node, int end, int x0, int x1, int x, int } n = end; - if (node->next && node->next->dest.kind == FZ_LINK_GOTO) + if (node->next && node->next->page >= 0) { - n = node->next->dest.ld.gotor.page; + n = node->next->page; } if (currentpage == p || (currentpage > p && currentpage < n)) { @@ -587,10 +586,10 @@ static void do_links(fz_link *link, int xofs, int yofs) { if (ui.hot == link) { - if (link->dest.kind == FZ_LINK_GOTO) - jump_to_page(link->dest.ld.gotor.page); - else if (link->dest.kind == FZ_LINK_URI) - open_browser(link->dest.ld.uri.uri); + if (fz_is_external_link(ctx, link->uri)) + open_browser(link->uri); + else + jump_to_page(fz_resolve_link(ctx, doc, link->uri)); } ui_needs_update = 1; } diff --git a/platform/ios/Classes/MuDocumentController.m b/platform/ios/Classes/MuDocumentController.m index 02efe1ee..1e9f954c 100644 --- a/platform/ios/Classes/MuDocumentController.m +++ b/platform/ios/Classes/MuDocumentController.m @@ -28,15 +28,12 @@ static void flattenOutline(NSMutableArray *titles, NSMutableArray *pages, fz_out indent[level * 4] = 0; while (outline) { - if (outline->dest.kind == FZ_LINK_GOTO) + int page = outline->page; + if (page >= 0 && outline->title) { - int page = outline->dest.ld.gotor.page; - if (page >= 0 && outline->title) - { - NSString *title = @(outline->title); - [titles addObject: [NSString stringWithFormat: @"%s%@", indent, title]]; - [pages addObject: @(page)]; - } + NSString *title = @(outline->title); + [titles addObject: [NSString stringWithFormat: @"%s%@", indent, title]]; + [pages addObject: @(page)]; } flattenOutline(titles, pages, outline->down, level + 1); outline = outline->next; diff --git a/platform/ios/Classes/MuHitView.m b/platform/ios/Classes/MuHitView.m index e94ac94a..b0a1ac4a 100644 --- a/platform/ios/Classes/MuHitView.m +++ b/platform/ios/Classes/MuHitView.m @@ -44,14 +44,19 @@ pageSize = CGSizeMake(100,100); while (link && hitCount < nelem(hitRects)) { - if (link->dest.kind == FZ_LINK_GOTO || link->dest.kind == FZ_LINK_URI) { + if (link->uri) { fz_rect bbox = link->rect; hitRects[hitCount].origin.x = bbox.x0; hitRects[hitCount].origin.y = bbox.y0; hitRects[hitCount].size.width = bbox.x1 - bbox.x0; hitRects[hitCount].size.height = bbox.y1 - bbox.y0; - linkPage[hitCount] = link->dest.kind == FZ_LINK_GOTO ? link->dest.ld.gotor.page : -1; - linkUrl[hitCount] = link->dest.kind == FZ_LINK_URI ? strdup(link->dest.ld.uri.uri) : nil; + if (fz_is_external_link(ctx, link->uri)) { + linkPage[hitCount] = -1; + linkUrl[hitCount] = strdup(link->uri); + } else { + linkPage[hitCount] = fz_resolve_link(ctx, doc, link->uri); + linkUrl[hitCount] = nil; + } hitCount++; } link = link->next; diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c index e2191c0d..6cf6716a 100644 --- a/platform/java/mupdf_native.c +++ b/platform/java/mupdf_native.c @@ -993,7 +993,7 @@ string_to_String(fz_context *ctx, JNIEnv *env, const char *str) return stringlen_to_String(ctx, env, str, strlen(str)); } -static inline jobject to_Outline_safe(fz_context *ctx, JNIEnv *env, fz_outline *outline) +static inline jobject to_Outline_safe(fz_context *ctx, JNIEnv *env, fz_document *doc, fz_outline *outline) { jobject joutline = NULL; jobject jarr = NULL; @@ -1025,17 +1025,17 @@ static inline jobject to_Outline_safe(fz_context *ctx, JNIEnv *env, fz_outline * if (!jtitle) return NULL; } - if (outline->dest.kind == FZ_LINK_GOTO) - jpage = outline->dest.ld.gotor.page; - else if (outline->dest.kind == FZ_LINK_URI) + if (fz_is_external_link(ctx, outline->uri)) { - juri = string_to_String(ctx, env, outline->dest.ld.uri.uri); + juri = string_to_String(ctx, env, outline->uri); if (!juri) return NULL; } + else + jpage = fz_resolve_link(ctx, doc, outline->uri); if (outline->down) { - jdown = to_Outline_safe(ctx, env, outline->down); + jdown = to_Outline_safe(ctx, env, doc, outline->down); if (!jdown) return NULL; } @@ -4265,7 +4265,7 @@ FUN(Document_loadOutline)(JNIEnv *env, jobject self) if (outline) { - joutline = to_Outline_safe(ctx, env, outline); + joutline = to_Outline_safe(ctx, env, doc, outline); if (!joutline) jni_throw(env, FZ_ERROR_GENERIC, "loadOutline failed"); fz_drop_outline(ctx, outline); @@ -4558,13 +4558,13 @@ FUN(Page_getLinks)(JNIEnv *env, jobject self) jbounds = to_Rect_safe(ctx, env, &link->rect); if (!jbounds) return NULL; - if (link->dest.kind == FZ_LINK_GOTO) - page = link->dest.ld.gotor.page; - else if (link->dest.kind == FZ_LINK_URI) + if (fz_is_external_link(ctx, link->uri)) { - juri = string_to_String(ctx, env, link->dest.ld.uri.uri); + juri = string_to_String(ctx, env, link->uri); if (!juri) return NULL; } + else + page = fz_resolve_link(ctx, link->doc, link->uri); jlink = (*env)->NewObject(env, cls_Link, mid_Link_init, jbounds, page, juri); (*env)->DeleteLocalRef(env, jbounds); diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c index 512feb2e..19983ee9 100644 --- a/platform/x11/pdfapp.c +++ b/platform/x11/pdfapp.c @@ -1737,10 +1737,10 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta wincursor(app, HAND); if (btn == 1 && state == 1 && !processed) { - if (link->dest.kind == FZ_LINK_URI) - pdfapp_gotouri(app, link->dest.ld.uri.uri); - else if (link->dest.kind == FZ_LINK_GOTO) - pdfapp_gotopage(app, link->dest.ld.gotor.page + 1); + if (fz_is_external_link(ctx, link->uri)) + pdfapp_gotouri(app, link->uri); + else + pdfapp_gotopage(app, fz_resolve_link(ctx, app->doc, link->uri) + 1); return; } } diff --git a/source/fitz/document.c b/source/fitz/document.c index 43fcb133..87ad3884 100644 --- a/source/fitz/document.c +++ b/source/fitz/document.c @@ -215,6 +215,15 @@ fz_load_outline(fz_context *ctx, fz_document *doc) return NULL; } +int +fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri) +{ + fz_ensure_layout(ctx, doc); + if (doc && doc->resolve_link) + return doc->resolve_link(ctx, doc, uri); + return -1; +} + void fz_layout_document(fz_context *ctx, fz_document *doc, float w, float h, float em) { diff --git a/source/fitz/link.c b/source/fitz/link.c index eaed1402..430c9bfe 100644 --- a/source/fitz/link.c +++ b/source/fitz/link.c @@ -1,51 +1,25 @@ #include "mupdf/fitz.h" -void -fz_drop_link_dest(fz_context *ctx, fz_link_dest *dest) -{ - if (!dest) - return; - - switch (dest->kind) - { - case FZ_LINK_NONE: - break; - case FZ_LINK_GOTO: - fz_free(ctx, dest->ld.gotor.dest); - break; - case FZ_LINK_URI: - fz_free(ctx, dest->ld.uri.uri); - break; - case FZ_LINK_LAUNCH: - fz_free(ctx, dest->ld.launch.file_spec); - break; - case FZ_LINK_NAMED: - fz_free(ctx, dest->ld.named.named); - break; - case FZ_LINK_GOTOR: - fz_free(ctx, dest->ld.gotor.file_spec); - break; - } -} - fz_link * -fz_new_link(fz_context *ctx, const fz_rect *bbox, fz_link_dest dest) +fz_new_link(fz_context *ctx, const fz_rect *bbox, void *doc, const char *uri) { fz_link *link; + link = fz_malloc_struct(ctx, fz_link); + link->refs = 1; + link->rect = *bbox; + link->next = NULL; + link->doc = doc; /* don't take reference */ + link->uri = NULL; + fz_try(ctx) - { - link = fz_malloc_struct(ctx, fz_link); - link->refs = 1; - } + link->uri = fz_strdup(ctx, uri); fz_catch(ctx) { - fz_drop_link_dest(ctx, &dest); + fz_drop_link(ctx, link); fz_rethrow(ctx); } - link->dest = dest; - link->rect = *bbox; - link->next = NULL; + return link; } @@ -61,8 +35,16 @@ fz_drop_link(fz_context *ctx, fz_link *link) while (fz_drop_imp(ctx, link, &link->refs)) { fz_link *next = link->next; - fz_drop_link_dest(ctx, &link->dest); + fz_free(ctx, link->uri); fz_free(ctx, link); link = next; } } + +int +fz_is_external_link(fz_context *ctx, const char *uri) +{ + while (*uri >= 'a' && *uri <= 'z') + ++uri; + return uri[0] == ':' && uri[1] == '/' && uri[2] == '/'; +} diff --git a/source/fitz/outline.c b/source/fitz/outline.c index 257c44c1..888212bc 100644 --- a/source/fitz/outline.c +++ b/source/fitz/outline.c @@ -22,7 +22,7 @@ fz_drop_outline(fz_context *ctx, fz_outline *outline) fz_outline *next = outline->next; fz_drop_outline(ctx, outline->down); fz_free(ctx, outline->title); - fz_drop_link_dest(ctx, &outline->dest); + fz_free(ctx, outline->uri); fz_free(ctx, outline); outline = next; } @@ -33,7 +33,7 @@ fz_debug_outline_xml_imp(fz_context *ctx, fz_output *out, fz_outline *outline, i { while (outline) { - fz_printf(ctx, out, "<outline title=%q page=\"%d\"", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); + fz_printf(ctx, out, "<outline title=%q uri=\"%s\"", outline->title, outline->uri); if (outline->down) { fz_printf(ctx, out, ">\n"); @@ -62,7 +62,7 @@ fz_print_outline_imp(fz_context *ctx, fz_output *out, fz_outline *outline, int l { for (i = 0; i < level; i++) fz_printf(ctx, out, "\t"); - fz_printf(ctx, out, "%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); + fz_printf(ctx, out, "%s\t%s\n", outline->title, outline->uri); if (outline->down) fz_print_outline_imp(ctx, out, outline->down, level + 1); outline = outline->next; diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c index efc4ac18..0616bb70 100644 --- a/source/html/epub-doc.c +++ b/source/html/epub-doc.c @@ -63,41 +63,40 @@ find_anchor_box(fz_html_box *box, const char *anchor, float page_h, int *page) return 0; } -static void -resolve_link_dest(fz_context *ctx, epub_document *doc, fz_link_dest *ld) +static int +epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest) { + epub_document *doc = (epub_document*)doc_; epub_chapter *ch; + int page = -1; - if (ld->kind == FZ_LINK_GOTO) - { - const char *dest = ld->ld.gotor.dest; - const char *s = strchr(dest, '#'); - int n = s ? s - dest : strlen(dest); - if (s && s[1] == 0) - s = NULL; + const char *s = strchr(dest, '#'); + int n = s ? s - dest : strlen(dest); + if (s && s[1] == 0) + s = NULL; - for (ch = doc->spine; ch; ch = ch->next) + for (ch = doc->spine; ch; ch = ch->next) + { + if (!strncmp(ch->path, dest, n) && ch->path[n] == 0) { - if (strncmp(ch->path, dest, n) || ch->path[n] != 0) - continue; - ld->ld.gotor.page = ch->start; + page = ch->start; if (s) { /* Search for a matching fragment */ - if (find_anchor_box(ch->html->root, s+1, ch->page_h, &ld->ld.gotor.page)) - continue; + find_anchor_box(ch->html->root, s+1, ch->page_h, &page); } - break; } } + + return page; } static void -epub_update_outline(fz_context *ctx, epub_document *doc, fz_outline *node) +epub_update_outline(fz_context *ctx, fz_document *doc, fz_outline *node) { while (node) { - resolve_link_dest(ctx, doc, &node->dest); + node->page = epub_resolve_link(ctx, doc, node->uri); epub_update_outline(ctx, doc, node->down); node = node->next; } @@ -124,7 +123,7 @@ epub_layout(fz_context *ctx, fz_document *doc_, float w, float h, float em) count += ceilf(ch->html->root->h / ch->page_h); } - epub_update_outline(ctx, doc, doc->outline); + epub_update_outline(ctx, doc_, doc->outline); } static int @@ -211,14 +210,13 @@ epub_load_links(fz_context *ctx, fz_page *page_) head = fz_load_html_links(ctx, ch->html, n - count, ch->page_h, ch->path); for (link = head; link; link = link->next) { + link->doc = doc; + /* Adjust for page margins */ link->rect.x0 += ch->page_margin[L]; link->rect.x1 += ch->page_margin[L]; link->rect.y0 += ch->page_margin[T]; link->rect.y1 += ch->page_margin[T]; - - /* Resolve local links */ - resolve_link_dest(ctx, doc, &link->dest); } return head; } @@ -343,9 +341,8 @@ epub_parse_ncx_imp(fz_context *ctx, epub_document *doc, fz_xml *node, char *base *tailp = outline = fz_new_outline(ctx); tailp = &(*tailp)->next; outline->title = fz_strdup(ctx, text); - outline->dest.kind = FZ_LINK_GOTO; - outline->dest.ld.gotor.dest = fz_strdup(ctx, path); - outline->dest.ld.gotor.page = 0; /* computed in epub_layout */ + outline->uri = fz_strdup(ctx, path); + outline->page = -1; outline->down = epub_parse_ncx_imp(ctx, doc, node, base_uri); } node = fz_xml_find_next(node, "navPoint"); @@ -494,6 +491,7 @@ epub_init(fz_context *ctx, fz_archive *zip) doc->super.drop_document = epub_drop_document; doc->super.layout = epub_layout; doc->super.load_outline = epub_load_outline; + doc->super.resolve_link = epub_resolve_link; doc->super.count_pages = epub_count_pages; doc->super.load_page = epub_load_page; doc->super.lookup_metadata = epub_lookup_metadata; diff --git a/source/html/html-layout.c b/source/html/html-layout.c index 54a96c1d..b700b59b 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -1902,7 +1902,7 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea fz_html_flow *next; char path[2048]; fz_rect bbox; - fz_link_dest dest; + char *dest; char *href; float end; @@ -1951,20 +1951,14 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea fz_urldecode(path); fz_cleanname(path); - memset(&dest, 0, sizeof dest); - dest.kind = FZ_LINK_GOTO; - dest.ld.gotor.dest = fz_strdup(ctx, path); - dest.ld.gotor.page = 0; /* computed in epub_load_links */ + dest = path; } else { - memset(&dest, 0, sizeof dest); - dest.kind = FZ_LINK_URI; - dest.ld.uri.uri = fz_strdup(ctx, href); - dest.ld.uri.is_map = 0; + dest = href; } - link = fz_new_link(ctx, &bbox, dest); + link = fz_new_link(ctx, &bbox, NULL, dest); link->next = head; head = link; } diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index a0220099..44c30fe9 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -1,19 +1,15 @@ #include "mupdf/pdf.h" static pdf_obj * -resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind kind, int depth) +resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, int depth) { if (depth > 10) /* Arbitrary to avoid infinite recursion */ return NULL; if (pdf_is_name(ctx, dest) || pdf_is_string(ctx, dest)) { - if (kind == FZ_LINK_GOTO) - { - dest = pdf_lookup_dest(ctx, doc, dest); - dest = resolve_dest_rec(ctx, doc, dest, kind, depth+1); - } - + dest = pdf_lookup_dest(ctx, doc, dest); + dest = resolve_dest_rec(ctx, doc, dest, depth+1); return dest; } @@ -25,7 +21,7 @@ resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind else if (pdf_is_dict(ctx, dest)) { dest = pdf_dict_get(ctx, dest, PDF_NAME_D); - return resolve_dest_rec(ctx, doc, dest, kind, depth+1); + return resolve_dest_rec(ctx, doc, dest, depth+1); } else if (pdf_is_indirect(ctx, dest)) @@ -35,193 +31,63 @@ resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind } static pdf_obj * -resolve_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind kind) +resolve_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest) { - return resolve_dest_rec(ctx, doc, dest, kind, 0); + return resolve_dest_rec(ctx, doc, dest, 0); } -fz_link_dest -pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, fz_link_kind kind, pdf_obj *dest) +char * +pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest) { - fz_link_dest ld; pdf_obj *obj; + char buf[40]; + char *ld; - int l_from_2 = 0; - int b_from_3 = 0; - int r_from_4 = 0; - int t_from_5 = 0; - int t_from_3 = 0; - int t_from_2 = 0; - int z_from_4 = 0; - - ld.kind = kind; - ld.ld.gotor.flags = 0; - ld.ld.gotor.lt.x = 0; - ld.ld.gotor.lt.y = 0; - ld.ld.gotor.rb.x = 0; - ld.ld.gotor.rb.y = 0; - ld.ld.gotor.page = -1; - ld.ld.gotor.dest = NULL; - - dest = resolve_dest(ctx, doc, dest, kind); + dest = resolve_dest(ctx, doc, dest); if (dest == NULL) { fz_warn(ctx, "undefined link destination"); - return ld; + return NULL; } if (pdf_is_name(ctx, dest)) { - ld.ld.gotor.dest = pdf_to_name(ctx, dest); - return ld; + ld = pdf_to_name(ctx, dest); + return fz_strdup(ctx, ld); } else if (pdf_is_string(ctx, dest)) { - ld.ld.gotor.dest = pdf_to_str_buf(ctx, dest); - return ld; + ld = pdf_to_str_buf(ctx, dest); + return fz_strdup(ctx, ld); } obj = pdf_array_get(ctx, dest, 0); if (pdf_is_int(ctx, obj)) - ld.ld.gotor.page = pdf_to_int(ctx, obj); - else - { - fz_try(ctx) - { - ld.ld.gotor.page = pdf_lookup_page_number(ctx, doc, obj); - } - fz_catch(ctx) - { - ld.kind = FZ_LINK_NONE; - return ld; - } - } - - obj = pdf_array_get(ctx, dest, 1); - if (!pdf_is_name(ctx, obj)) - return ld; - - if (pdf_name_eq(ctx, PDF_NAME_XYZ, obj)) - { - l_from_2 = t_from_3 = z_from_4 = 1; - ld.ld.gotor.flags |= fz_link_flag_r_is_zoom; - } - else if ((pdf_name_eq(ctx, PDF_NAME_Fit, obj)) || (pdf_name_eq(ctx, PDF_NAME_FitB, obj))) { - ld.ld.gotor.flags |= fz_link_flag_fit_h; - ld.ld.gotor.flags |= fz_link_flag_fit_v; + sprintf(buf, "#%d", pdf_to_int(ctx, obj) + 1); + return fz_strdup(ctx, buf); } - else if ((pdf_name_eq(ctx, PDF_NAME_FitH, obj)) || (pdf_name_eq(ctx, PDF_NAME_FitBH, obj))) - { - t_from_2 = 1; - ld.ld.gotor.flags |= fz_link_flag_fit_h; - } - else if ((pdf_name_eq(ctx, PDF_NAME_FitV, obj)) || (pdf_name_eq(ctx, PDF_NAME_FitBV, obj))) - { - l_from_2 = 1; - ld.ld.gotor.flags |= fz_link_flag_fit_v; - } - else if (pdf_name_eq(ctx, PDF_NAME_FitR, obj)) - { - l_from_2 = b_from_3 = r_from_4 = t_from_5 = 1; - ld.ld.gotor.flags |= fz_link_flag_fit_h; - ld.ld.gotor.flags |= fz_link_flag_fit_v; - } - - if (l_from_2) - { - obj = pdf_array_get(ctx, dest, 2); - if (pdf_is_int(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_l_valid; - ld.ld.gotor.lt.x = pdf_to_int(ctx, obj); - } - else if (pdf_is_real(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_l_valid; - ld.ld.gotor.lt.x = pdf_to_real(ctx, obj); - } - } - if (b_from_3) - { - obj = pdf_array_get(ctx, dest, 3); - if (pdf_is_int(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_b_valid; - ld.ld.gotor.rb.y = pdf_to_int(ctx, obj); - } - else if (pdf_is_real(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_b_valid; - ld.ld.gotor.rb.y = pdf_to_real(ctx, obj); - } - } - if (r_from_4) - { - obj = pdf_array_get(ctx, dest, 4); - if (pdf_is_int(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_r_valid; - ld.ld.gotor.rb.x = pdf_to_int(ctx, obj); - } - else if (pdf_is_real(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_r_valid; - ld.ld.gotor.rb.x = pdf_to_real(ctx, obj); - } - } - if (t_from_5 || t_from_3 || t_from_2) - { - if (t_from_5) - obj = pdf_array_get(ctx, dest, 5); - else if (t_from_3) - obj = pdf_array_get(ctx, dest, 3); - else - obj = pdf_array_get(ctx, dest, 2); - if (pdf_is_int(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_t_valid; - ld.ld.gotor.lt.y = pdf_to_int(ctx, obj); - } - else if (pdf_is_real(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_t_valid; - ld.ld.gotor.lt.y = pdf_to_real(ctx, obj); - } - } - if (z_from_4) + else { - obj = pdf_array_get(ctx, dest, 4); - if (pdf_is_int(ctx, obj)) + int page = pdf_lookup_page_number(ctx, doc, obj); + if (page >= 0) { - ld.ld.gotor.flags |= fz_link_flag_r_valid; - ld.ld.gotor.rb.x = pdf_to_int(ctx, obj); - } - else if (pdf_is_real(ctx, obj)) - { - ld.ld.gotor.flags |= fz_link_flag_r_valid; - ld.ld.gotor.rb.x = pdf_to_real(ctx, obj); + sprintf(buf, "#%d", page + 1); + return fz_strdup(ctx, buf); } } - /* Duplicate the values out for the sake of stupid clients */ - if ((ld.ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid)) == fz_link_flag_l_valid) - ld.ld.gotor.rb.x = ld.ld.gotor.lt.x; - if ((ld.ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid | fz_link_flag_r_is_zoom)) == fz_link_flag_r_valid) - ld.ld.gotor.lt.x = ld.ld.gotor.rb.x; - if ((ld.ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_t_valid) - ld.ld.gotor.rb.y = ld.ld.gotor.lt.y; - if ((ld.ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_b_valid) - ld.ld.gotor.lt.y = ld.ld.gotor.rb.y; - - return ld; + return NULL; } char * -pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec) +pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec, pdf_obj *dest) { pdf_obj *filename=NULL; char *path = NULL; + char *uri = NULL; + char buf[256]; + size_t n; if (pdf_is_string(ctx, file_spec)) filename = file_spec; @@ -260,54 +126,56 @@ pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec) } } #endif - return path; + + if (pdf_is_array(ctx, dest)) + fz_snprintf(buf, sizeof buf, "#%d", pdf_to_int(ctx, pdf_array_get(ctx, dest, 0)) + 1); + else if (pdf_is_name(ctx, dest)) + fz_snprintf(buf, sizeof buf, "#%s", pdf_to_name(ctx, dest)); + else if (pdf_is_stream(ctx, dest)) + fz_snprintf(buf, sizeof buf, "#%s", pdf_to_str_buf(ctx, dest)); + else + buf[0] = 0; + + n = 7 + strlen(path) + strlen(buf) + 1; + uri = fz_malloc(ctx, n); + fz_strlcpy(uri, "file://", n); + fz_strlcat(uri, path, n); + fz_strlcat(uri, buf, n); + fz_free(ctx, path); + return uri; } -fz_link_dest -pdf_parse_action(fz_context *ctx, pdf_document *doc, pdf_obj *action) +char * +pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *action) { - fz_link_dest ld; pdf_obj *obj, *dest, *file_spec; - ld.kind = FZ_LINK_NONE; - if (!action) - return ld; + return NULL; obj = pdf_dict_get(ctx, action, PDF_NAME_S); if (pdf_name_eq(ctx, PDF_NAME_GoTo, obj)) { dest = pdf_dict_get(ctx, action, PDF_NAME_D); - ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, dest); + return pdf_parse_link_dest(ctx, doc, dest); } else if (pdf_name_eq(ctx, PDF_NAME_URI, obj)) { - ld.kind = FZ_LINK_URI; - ld.ld.uri.is_map = pdf_to_bool(ctx, pdf_dict_get(ctx, action, PDF_NAME_IsMap)); - ld.ld.uri.uri = pdf_to_utf8(ctx, pdf_dict_get(ctx, action, PDF_NAME_URI)); + return pdf_to_utf8(ctx, pdf_dict_get(ctx, action, PDF_NAME_URI)); } else if (pdf_name_eq(ctx, PDF_NAME_Launch, obj)) { - ld.kind = FZ_LINK_LAUNCH; file_spec = pdf_dict_get(ctx, action, PDF_NAME_F); - ld.ld.launch.file_spec = pdf_parse_file_spec(ctx, doc, file_spec); - ld.ld.launch.new_window = pdf_to_int(ctx, pdf_dict_get(ctx, action, PDF_NAME_NewWindow)); - ld.ld.launch.is_uri = pdf_name_eq(ctx, PDF_NAME_URL, pdf_dict_get(ctx, file_spec, PDF_NAME_FS)); - } - else if (pdf_name_eq(ctx, PDF_NAME_Named, obj)) - { - ld.kind = FZ_LINK_NAMED; - ld.ld.named.named = fz_strdup(ctx, pdf_to_name(ctx, pdf_dict_get(ctx, action, PDF_NAME_N))); + return pdf_parse_file_spec(ctx, doc, file_spec, NULL); } else if (pdf_name_eq(ctx, PDF_NAME_GoToR, obj)) { dest = pdf_dict_get(ctx, action, PDF_NAME_D); file_spec = pdf_dict_get(ctx, action, PDF_NAME_F); - ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTOR, dest); - ld.ld.gotor.file_spec = pdf_parse_file_spec(ctx, doc, file_spec); - ld.ld.gotor.new_window = pdf_to_int(ctx, pdf_dict_get(ctx, action, PDF_NAME_NewWindow)); + return pdf_parse_file_spec(ctx, doc, file_spec, dest); } - return ld; + + return NULL; } static fz_link * @@ -316,31 +184,34 @@ pdf_load_link(fz_context *ctx, pdf_document *doc, pdf_obj *dict, const fz_matrix pdf_obj *action; pdf_obj *obj; fz_rect bbox; - fz_link_dest ld; + char *uri; + fz_link *link; obj = pdf_dict_get(ctx, dict, PDF_NAME_Rect); - if (obj) - pdf_to_rect(ctx, obj, &bbox); - else - bbox = fz_empty_rect; + if (!obj) + return NULL; + pdf_to_rect(ctx, obj, &bbox); fz_transform_rect(&bbox, page_ctm); obj = pdf_dict_get(ctx, dict, PDF_NAME_Dest); if (obj) - ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, obj); + uri = pdf_parse_link_dest(ctx, doc, obj); else { action = pdf_dict_get(ctx, dict, PDF_NAME_A); /* fall back to additional action button's down/up action */ if (!action) action = pdf_dict_geta(ctx, pdf_dict_get(ctx, dict, PDF_NAME_AA), PDF_NAME_U, PDF_NAME_D); - - ld = pdf_parse_action(ctx, doc, action); + uri = pdf_parse_link_action(ctx, doc, action); } - if (ld.kind == FZ_LINK_NONE) + + if (!uri) return NULL; - return fz_new_link(ctx, &bbox, ld); + + link = fz_new_link(ctx, &bbox, doc, uri); + fz_free(ctx, uri); + return link; } fz_link * @@ -383,6 +254,15 @@ pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, const return head; } +int +pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri) +{ + if (uri && uri[0] == '#') + return fz_atoi(uri + 1) - 1; + fz_warn(ctx, "unknown link uri '%s'", uri); + return -1; +} + static void pdf_drop_annot_imp(fz_context *ctx, pdf_annot *annot) { diff --git a/source/pdf/pdf-outline.c b/source/pdf/pdf-outline.c index c9fd35fe..d82db02c 100644 --- a/source/pdf/pdf-outline.c +++ b/source/pdf/pdf-outline.c @@ -27,9 +27,13 @@ pdf_load_outline_imp(fz_context *ctx, pdf_document *doc, pdf_obj *dict) node->title = pdf_to_utf8(ctx, obj); if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_Dest)) != NULL) - node->dest = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, obj); + node->uri = pdf_parse_link_dest(ctx, doc, obj); else if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_A)) != NULL) - node->dest = pdf_parse_action(ctx, doc, obj); + node->uri = pdf_parse_link_action(ctx, doc, obj); + else + node->uri = NULL; + + node->page = pdf_resolve_link(ctx, doc, node->uri); obj = pdf_dict_get(ctx, dict, PDF_NAME_First); if (obj) diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c index 0cfb5dae..7c7005e3 100644 --- a/source/pdf/pdf-page.c +++ b/source/pdf/pdf-page.c @@ -204,7 +204,7 @@ int pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name) { pdf_obj *needle, *dest; - fz_link_dest ld; + char *uri; needle = pdf_new_string(ctx, doc, name, strlen(name)); fz_try(ctx) @@ -214,8 +214,8 @@ pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name) fz_catch(ctx) fz_rethrow(ctx); - ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, dest); - return ld.ld.gotor.page; + uri = pdf_parse_link_dest(ctx, doc, dest); + return pdf_resolve_link(ctx, doc, uri); } static pdf_obj * diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c index c46d9f52..070e0946 100644 --- a/source/pdf/pdf-xref.c +++ b/source/pdf/pdf-xref.c @@ -2343,6 +2343,7 @@ pdf_new_document(fz_context *ctx, fz_stream *file) doc->super.authenticate_password = (fz_document_authenticate_password_fn *)pdf_authenticate_password; doc->super.has_permission = (fz_document_has_permission_fn *)pdf_has_permission; doc->super.load_outline = (fz_document_load_outline_fn *)pdf_load_outline; + doc->super.resolve_link = (fz_document_resolve_link_fn *)pdf_resolve_link; doc->super.count_pages = (fz_document_count_pages_fn *)pdf_count_pages; doc->super.load_page = (fz_document_load_page_fn *)pdf_load_page; doc->super.lookup_metadata = (fz_document_lookup_metadata_fn *)pdf_lookup_metadata; diff --git a/source/tools/murun.c b/source/tools/murun.c index fc887105..079a8c3c 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -1601,14 +1601,17 @@ static void to_outline(js_State *J, fz_outline *outline) js_pushundefined(J); js_setproperty(J, -2, "title"); - if (outline->dest.kind == FZ_LINK_GOTO) { - js_pushnumber(J, outline->dest.ld.gotor.page); - js_setproperty(J, -2, "page"); - } - if (outline->dest.kind == FZ_LINK_URI) { - js_pushstring(J, outline->dest.ld.uri.uri); - js_setproperty(J, -2, "uri"); - } + if (outline->uri) + js_pushstring(J, outline->uri); + else + js_pushundefined(J); + js_setproperty(J, -2, "uri"); + + if (outline->page >= 0) + js_pushnumber(J, outline->page); + else + js_pushundefined(J); + js_setproperty(J, -2, "page"); if (outline->down) { to_outline(J, outline->down); @@ -1821,14 +1824,8 @@ static void ffi_Page_getLinks(js_State *J) ffi_pushrect(J, link->rect); js_setproperty(J, -2, "bounds"); - if (link->dest.kind == FZ_LINK_GOTO) { - js_pushnumber(J, link->dest.ld.gotor.page); - js_setproperty(J, -2, "page"); - } - if (link->dest.kind == FZ_LINK_URI) { - js_pushstring(J, link->dest.ld.uri.uri); - js_setproperty(J, -2, "uri"); - } + js_pushstring(J, link->uri); + js_setproperty(J, -2, "uri"); js_setindex(J, -2, i++); } diff --git a/source/xps/xps-link.c b/source/xps/xps-link.c index 9986d25f..1b2423ad 100644 --- a/source/xps/xps-link.c +++ b/source/xps/xps-link.c @@ -10,23 +10,7 @@ xps_load_links_in_element(fz_context *ctx, xps_document *doc, const fz_matrix *c static void xps_add_link(fz_context *ctx, xps_document *doc, const fz_rect *area, char *base_uri, char *target_uri, fz_link **head) { - fz_link_dest dest; - fz_link *link; - - memset(&dest, 0, sizeof dest); - - if (xps_url_is_remote(ctx, doc, target_uri)) - { - dest.kind = FZ_LINK_URI; - dest.ld.uri.uri = fz_strdup(ctx, target_uri); - } - else - { - dest.kind = FZ_LINK_GOTO; - dest.ld.gotor.page = xps_lookup_link_target(ctx, doc, target_uri); - } - - link = fz_new_link(ctx, area, dest); + fz_link *link = fz_new_link(ctx, area, doc, target_uri); link->next = *head; *head = link; } diff --git a/source/xps/xps-outline.c b/source/xps/xps-outline.c index 50eaf960..1fe294fb 100644 --- a/source/xps/xps-outline.c +++ b/source/xps/xps-outline.c @@ -33,9 +33,8 @@ xps_parse_document_outline(fz_context *ctx, xps_document *doc, fz_xml *root) entry = fz_new_outline(ctx); entry->title = fz_strdup(ctx, description); - entry->dest.kind = FZ_LINK_GOTO; - entry->dest.ld.gotor.flags = 0; - entry->dest.ld.gotor.page = xps_lookup_link_target(ctx, doc, target); + entry->uri = fz_strdup(ctx, target); + entry->page = xps_lookup_link_target(ctx, doc, target); entry->down = NULL; entry->next = NULL; diff --git a/source/xps/xps-zip.c b/source/xps/xps-zip.c index b2cc9e77..ba9947c7 100644 --- a/source/xps/xps-zip.c +++ b/source/xps/xps-zip.c @@ -231,6 +231,7 @@ xps_init_document(fz_context *ctx, xps_document *doc) doc->super.refs = 1; doc->super.drop_document = (fz_document_drop_fn *)xps_drop_document; doc->super.load_outline = (fz_document_load_outline_fn *)xps_load_outline; + doc->super.resolve_link = (fz_document_resolve_link_fn *)xps_lookup_link_target; doc->super.count_pages = (fz_document_count_pages_fn *)xps_count_pages; doc->super.load_page = (fz_document_load_page_fn *)xps_load_page; doc->super.lookup_metadata = (fz_document_lookup_metadata_fn *)xps_lookup_metadata; |