diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2011-11-10 01:52:40 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-11-10 01:52:40 +0100 |
commit | 97d00440c043b712a2d16134e3b52850c7b36d47 (patch) | |
tree | e7b838f3b7c714037bb238b0c4d17ab4aaa3e0ed /xps/xps_doc.c | |
parent | c445538b312a45435df87086eed2e19b68ed5bc1 (diff) | |
download | mupdf-97d00440c043b712a2d16134e3b52850c7b36d47.tar.xz |
Add XPS outline parsing and move outline data struct to fz_outline.
Diffstat (limited to 'xps/xps_doc.c')
-rw-r--r-- | xps/xps_doc.c | 113 |
1 files changed, 89 insertions, 24 deletions
diff --git a/xps/xps_doc.c b/xps/xps_doc.c index 5719e7f8..e0ab7d61 100644 --- a/xps/xps_doc.c +++ b/xps/xps_doc.c @@ -1,6 +1,20 @@ #include "fitz.h" #include "muxps.h" +static void +xps_rels_for_part(char *buf, char *name, int buflen) +{ + char *p, *basename; + p = strrchr(name, '/'); + basename = p ? p + 1 : name; + fz_strlcpy(buf, name, buflen); + p = strrchr(buf, '/'); + if (p) *p = 0; + fz_strlcat(buf, "/_rels/", buflen); + fz_strlcat(buf, basename, buflen); + fz_strlcat(buf, ".rels", buflen); +} + /* * The FixedDocumentSequence and FixedDocument parts determine * which parts correspond to actual pages, and the page order. @@ -23,7 +37,7 @@ xps_debug_page_list(xps_context *ctx) while (page) { - printf("page %s w=%d h=%d\n", page->name, page->width, page->height); + printf("page[%d] %s w=%d h=%d\n", page->number, page->name, page->width, page->height); page = page->next; } } @@ -40,6 +54,7 @@ xps_add_fixed_document(xps_context *ctx, char *name) fixdoc = fz_malloc(sizeof(xps_document)); fixdoc->name = fz_strdup(name); + fixdoc->outline = NULL; fixdoc->next = NULL; if (!ctx->first_fixdoc) @@ -66,6 +81,7 @@ xps_add_fixed_page(xps_context *ctx, char *name, int width, int height) page = fz_malloc(sizeof(xps_page)); page->name = fz_strdup(name); + page->number = ctx->page_count++; page->width = width; page->height = height; page->root = NULL; @@ -84,6 +100,42 @@ xps_add_fixed_page(xps_context *ctx, char *name, int width, int height) } static void +xps_add_link_target(xps_context *ctx, char *name) +{ + xps_page *page = ctx->last_page; + xps_target *target = fz_malloc(sizeof *target); + target->name = fz_strdup(name); + target->page = page->number; + target->next = ctx->target; + ctx->target = target; +} + +int +xps_find_link_target(xps_context *ctx, char *target_uri) +{ + xps_target *target; + char *needle = strrchr(target_uri, '#'); + needle = needle ? needle + 1 : target_uri; + for (target = ctx->target; target; target = target->next) + if (!strcmp(target->name, needle)) + return target->page; + return 0; +} + +static void +xps_free_link_targets(xps_context *ctx) +{ + xps_target *target = ctx->target, *next; + while (target) + { + next = target->next; + fz_free(target->name); + fz_free(target); + target = next; + } +} + +static void xps_free_fixed_pages(xps_context *ctx) { xps_page *page = ctx->first_page; @@ -102,13 +154,13 @@ xps_free_fixed_pages(xps_context *ctx) static void xps_free_fixed_documents(xps_context *ctx) { - xps_document *doc = ctx->first_fixdoc; - while (doc) + xps_document *fixdoc = ctx->first_fixdoc; + while (fixdoc) { - xps_document *next = doc->next; - fz_free(doc->name); - fz_free(doc); - doc = next; + xps_document *next = fixdoc->next; + fz_free(fixdoc->name); + fz_free(fixdoc); + fixdoc = next; } ctx->first_fixdoc = NULL; ctx->last_fixdoc = NULL; @@ -119,6 +171,7 @@ xps_free_page_list(xps_context *ctx) { xps_free_fixed_documents(ctx); xps_free_fixed_pages(ctx); + xps_free_link_targets(ctx); } /* @@ -126,12 +179,10 @@ xps_free_page_list(xps_context *ctx) */ static void -xps_parse_metadata_imp(xps_context *ctx, xml_element *item) +xps_parse_metadata_imp(xps_context *ctx, xml_element *item, xps_document *fixdoc) { while (item) { - xps_parse_metadata_imp(ctx, xml_down(item)); - if (!strcmp(xml_tag(item), "Relationship")) { char *target = xml_att(item, "Target"); @@ -142,6 +193,8 @@ xps_parse_metadata_imp(xps_context *ctx, xml_element *item) xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); if (!strcmp(type, REL_START_PART)) ctx->start_part = fz_strdup(tgtbuf); + if (!strcmp(type, REL_DOC_STRUCTURE) && fixdoc) + fixdoc->outline = fz_strdup(tgtbuf); } } @@ -171,12 +224,21 @@ xps_parse_metadata_imp(xps_context *ctx, xml_element *item) } } + if (!strcmp(xml_tag(item), "LinkTarget")) + { + char *name = xml_att(item, "Name"); + if (name) + xps_add_link_target(ctx, name); + } + + xps_parse_metadata_imp(ctx, xml_down(item), fixdoc); + item = xml_next(item); } } static int -xps_parse_metadata(xps_context *ctx, xps_part *part) +xps_parse_metadata(xps_context *ctx, xps_part *part, xps_document *fixdoc) { xml_element *root; char buf[1024]; @@ -203,7 +265,7 @@ xps_parse_metadata(xps_context *ctx, xps_part *part) if (!root) return fz_rethrow(-1, "cannot parse metadata part '%s'", part->name); - xps_parse_metadata_imp(ctx, root); + xps_parse_metadata_imp(ctx, root, fixdoc); xml_free_element(root); @@ -214,7 +276,7 @@ xps_parse_metadata(xps_context *ctx, xps_part *part) } static int -xps_read_and_process_metadata_part(xps_context *ctx, char *name) +xps_read_and_process_metadata_part(xps_context *ctx, char *name, xps_document *fixdoc) { xps_part *part; int code; @@ -223,7 +285,7 @@ xps_read_and_process_metadata_part(xps_context *ctx, char *name) if (!part) return fz_rethrow(-1, "cannot read zip part '%s'", name); - code = xps_parse_metadata(ctx, part); + code = xps_parse_metadata(ctx, part, fixdoc); if (code) return fz_rethrow(code, "cannot process metadata part '%s'", name); @@ -235,23 +297,30 @@ xps_read_and_process_metadata_part(xps_context *ctx, char *name) int xps_read_page_list(xps_context *ctx) { - xps_document *doc; + xps_document *fixdoc; int code; - code = xps_read_and_process_metadata_part(ctx, "/_rels/.rels"); + code = xps_read_and_process_metadata_part(ctx, "/_rels/.rels", NULL); if (code) return fz_rethrow(code, "cannot process root relationship part"); if (!ctx->start_part) return fz_throw("cannot find fixed document sequence start part"); - code = xps_read_and_process_metadata_part(ctx, ctx->start_part); + code = xps_read_and_process_metadata_part(ctx, ctx->start_part, NULL); if (code) return fz_rethrow(code, "cannot process FixedDocumentSequence part"); - for (doc = ctx->first_fixdoc; doc; doc = doc->next) + for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next) { - code = xps_read_and_process_metadata_part(ctx, doc->name); + char relbuf[1024]; + xps_rels_for_part(relbuf, fixdoc->name, sizeof relbuf); + + code = xps_read_and_process_metadata_part(ctx, relbuf, fixdoc); + if (code) + fz_catch(code, "cannot process FixedDocument rels part"); + + code = xps_read_and_process_metadata_part(ctx, fixdoc->name, fixdoc); if (code) return fz_rethrow(code, "cannot process FixedDocument part"); } @@ -262,11 +331,7 @@ xps_read_page_list(xps_context *ctx) int xps_count_pages(xps_context *ctx) { - xps_page *page; - int n = 0; - for (page = ctx->first_page; page; page = page->next) - n ++; - return n; + return ctx->page_count; } static int |