summaryrefslogtreecommitdiff
path: root/xps/xps_doc.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2011-11-10 01:52:40 +0100
committerTor Andersson <tor.andersson@artifex.com>2011-11-10 01:52:40 +0100
commit97d00440c043b712a2d16134e3b52850c7b36d47 (patch)
treee7b838f3b7c714037bb238b0c4d17ab4aaa3e0ed /xps/xps_doc.c
parentc445538b312a45435df87086eed2e19b68ed5bc1 (diff)
downloadmupdf-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.c113
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