int pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri, float *xp, float *yp) { if (uri && uri[0] == '#') { int page = fz_atoi(uri + 1) - 1; if (xp || yp) { const char *x = strchr(uri, ','); const char *y = strrchr(uri, ','); if (x && y) { pdf_obj *obj; fz_matrix ctm; fz_point p; p.x = x ? fz_atoi(x + 1) : 0; p.y = y ? fz_atoi(y + 1) : 0; obj = pdf_lookup_page_obj(ctx, doc, page); pdf_page_obj_transform(ctx, obj, NULL, &ctm); fz_transform_point(&p, &ctm); if (xp) *xp = p.x; if (yp) *yp = p.y; } } return page; } fz_warn(ctx, "unknown link uri '%s'", uri); return -1; }
char * pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest) { pdf_obj *obj, *pageobj; fz_rect mediabox; fz_matrix pagectm; const char *ld; int page, x, y, h; dest = resolve_dest(ctx, doc, dest); if (dest == NULL) { fz_warn(ctx, "undefined link destination"); return NULL; } if (pdf_is_name(ctx, dest)) { ld = pdf_to_name(ctx, dest); return fz_strdup(ctx, ld); } else if (pdf_is_string(ctx, dest)) { ld = pdf_to_str_buf(ctx, dest); return fz_strdup(ctx, ld); } pageobj = pdf_array_get(ctx, dest, 0); if (pdf_is_int(ctx, pageobj)) { page = pdf_to_int(ctx, pageobj); pageobj = pdf_lookup_page_obj(ctx, doc, page); } else { fz_try(ctx) page = pdf_lookup_page_number(ctx, doc, pageobj); fz_catch(ctx) page = -1; } if (page < 0) return NULL; obj = pdf_array_get(ctx, dest, 1); if (obj) { /* Link coords use a coordinate space that does not seem to respect Rotate or UserUnit. */ /* All we need to do is figure out the page height to flip the coordinate space. */ pdf_page_obj_transform(ctx, pageobj, &mediabox, &pagectm); mediabox = fz_transform_rect(mediabox, pagectm); h = mediabox.y1 - mediabox.y0; if (pdf_name_eq(ctx, obj, PDF_NAME(XYZ))) { x = pdf_array_get_int(ctx, dest, 2); y = h - pdf_array_get_int(ctx, dest, 3); } else if (pdf_name_eq(ctx, obj, PDF_NAME(FitR))) { x = pdf_array_get_int(ctx, dest, 2); y = h - pdf_array_get_int(ctx, dest, 5); } else if (pdf_name_eq(ctx, obj, PDF_NAME(FitH)) || pdf_name_eq(ctx, obj, PDF_NAME(FitBH))) { x = 0; y = h - pdf_array_get_int(ctx, dest, 2); } else if (pdf_name_eq(ctx, obj, PDF_NAME(FitV)) || pdf_name_eq(ctx, obj, PDF_NAME(FitBV))) { x = pdf_array_get_int(ctx, dest, 2); y = 0; } else { x = 0; y = 0; } return fz_asprintf(ctx, "#%d,%d,%d", page + 1, x, y); } return fz_asprintf(ctx, "#%d", page + 1); }