summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/html.h2
-rw-r--r--source/html/epub-doc.c42
-rw-r--r--source/html/html-layout.c39
3 files changed, 48 insertions, 35 deletions
diff --git a/include/mupdf/html.h b/include/mupdf/html.h
index 259333a4..dd58b814 100644
--- a/include/mupdf/html.h
+++ b/include/mupdf/html.h
@@ -207,7 +207,7 @@ struct fz_html_box_s
float em;
fz_html_box *up, *down, *last, *next;
fz_html_flow *flow_head, **flow_tail;
- char *a_href;
+ char *id, *href;
fz_css_style style;
};
diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c
index 0616bb70..f9d9e6aa 100644
--- a/source/html/epub-doc.c
+++ b/source/html/epub-doc.c
@@ -35,32 +35,40 @@ struct epub_page_s
};
static int
-find_anchor_flow(fz_html_flow *flow, const char *anchor, float page_h, int *page)
+find_anchor_flow(fz_html_flow *flow, const char *anchor, float page_h)
{
while (flow)
{
- if (flow->type == FLOW_ANCHOR && !strcmp(anchor, flow->content.text))
- {
- *page += (int)(flow->y / page_h);
- return 1;
- }
+ if (flow->box->id && !strcmp(anchor, flow->box->id))
+ return flow->y / page_h;
flow = flow->next;
}
- return 0;
+ return -1;
}
static int
-find_anchor_box(fz_html_box *box, const char *anchor, float page_h, int *page)
+find_anchor_box(fz_html_box *box, const char *anchor, float page_h)
{
+ int page;
while (box)
{
- if (box->flow_head && find_anchor_flow(box->flow_head, anchor, page_h, page))
- return 1;
- if (box->down && find_anchor_box(box->down, anchor, page_h, page))
- return 1;
+ if (box->id && !strcmp(anchor, box->id))
+ return box->y / page_h;
+ if (box->type == BOX_FLOW)
+ {
+ page = find_anchor_flow(box->flow_head, anchor, page_h);
+ if (page >= 0)
+ return page;
+ }
+ else
+ {
+ page = find_anchor_box(box->down, anchor, page_h);
+ if (page >= 0)
+ return page;
+ }
box = box->next;
}
- return 0;
+ return -1;
}
static int
@@ -79,16 +87,18 @@ epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest)
{
if (!strncmp(ch->path, dest, n) && ch->path[n] == 0)
{
- page = ch->start;
if (s)
{
/* Search for a matching fragment */
- find_anchor_box(ch->html->root, s+1, ch->page_h, &page);
+ page = find_anchor_box(ch->html->root, s+1, ch->page_h);
+ if (page >= 0)
+ return ch->start + page;
}
+ return ch->start;
}
}
- return page;
+ return -1;
}
static void
diff --git a/source/html/html-layout.c b/source/html/html-layout.c
index b700b59b..fc0874ae 100644
--- a/source/html/html-layout.c
+++ b/source/html/html-layout.c
@@ -198,12 +198,9 @@ static void add_flow_image(fz_context *ctx, fz_pool *pool, fz_html_box *top, fz_
flow->content.image = fz_keep_image(ctx, img);
}
-static void add_flow_anchor(fz_context *ctx, fz_pool *pool, fz_html_box *top, fz_html_box *inline_box, const char *anchor)
+static void add_flow_anchor(fz_context *ctx, fz_pool *pool, fz_html_box *top, fz_html_box *inline_box)
{
- fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_ANCHOR);
- size_t len = strlen(anchor)+1;
- flow->content.text = fz_pool_alloc(ctx, pool, len);
- memcpy(flow->content.text, anchor, len);
+ (void)add_flow(ctx, pool, top, inline_box, FLOW_ANCHOR);
}
static fz_html_flow *split_flow(fz_context *ctx, fz_pool *pool, fz_html_flow *flow, size_t offset)
@@ -425,13 +422,13 @@ static fz_image *load_html_image(fz_context *ctx, fz_archive *zip, const char *b
return img;
}
-static void generate_anchor(fz_context *ctx, fz_html_box *box, const char *id, struct genstate *g)
+static void generate_anchor(fz_context *ctx, fz_html_box *box, struct genstate *g)
{
fz_pool *pool = g->pool;
fz_html_box *flow = box;
while (flow->type != BOX_FLOW)
flow = flow->up;
- add_flow_anchor(ctx, pool, flow, box, id);
+ add_flow_anchor(ctx, pool, flow, box);
}
static void generate_image(fz_context *ctx, fz_html_box *box, fz_image *img, struct genstate *g)
@@ -704,6 +701,10 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, fz_html_box *top,
box = new_box(ctx, g->pool, child_dir);
fz_apply_css_style(ctx, g->set, &box->style, &match);
+ id = fz_xml_att(node, "id");
+ if (id)
+ box->id = fz_pool_strdup(ctx, g->pool, id);
+
if (display == DIS_BLOCK || display == DIS_INLINE_BLOCK)
{
top = insert_block_box(ctx, box, top);
@@ -716,14 +717,13 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, fz_html_box *top,
else if (display == DIS_INLINE)
{
insert_inline_box(ctx, box, top, child_dir, g);
+ if (id)
+ generate_anchor(ctx, box, g);
if (tag[0]=='a' && tag[1]==0)
{
- id = fz_xml_att(node, "id");
- if (id)
- generate_anchor(ctx, box, id, g);
href = fz_xml_att(node, "href");
if (href)
- box->a_href = fz_pool_strdup(ctx, g->pool, href);
+ box->href = fz_pool_strdup(ctx, g->pool, href);
}
}
@@ -1206,6 +1206,7 @@ static void layout_flow_inline(fz_context *ctx, fz_html_box *box, fz_html_box *t
{
while (box)
{
+ box->y = top->y;
box->em = fz_from_css_number(box->style.font_size, top->em, top->em);
if (box->down)
layout_flow_inline(ctx, box->down, box);
@@ -1908,7 +1909,7 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea
while (flow)
{
- href = flow->box->a_href;
+ href = flow->box->href;
next = flow->next;
if (href && (int)(flow->y / page_h) == page)
{
@@ -1917,8 +1918,8 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea
while (next &&
next->y == flow->y &&
next->h == flow->h &&
- next->box->a_href &&
- !strcmp(href, next->box->a_href))
+ next->box->href &&
+ !strcmp(href, next->box->href))
{
end = next->x + next->w;
next = next->next;
@@ -2187,9 +2188,10 @@ fz_print_html_box(fz_context *ctx, fz_html_box *box, int pstyle, int level)
if (box->list_item)
printf(" list=%d", box->list_item);
-
- if (box->a_href)
- printf(" href='%s'", box->a_href);
+ if (box->id)
+ printf(" id='%s'", box->id);
+ if (box->href)
+ printf(" href='%s'", box->href);
if (box->down || box->flow_head)
printf(" {\n");
@@ -2301,7 +2303,8 @@ static void fragment_cb(const uint32_t *fragment,
len = 1;
}
- else if (data->flow->type == FLOW_BREAK || data->flow->type == FLOW_SBREAK || data->flow->type == FLOW_SHYPHEN)
+ else if (data->flow->type == FLOW_BREAK || data->flow->type == FLOW_SBREAK ||
+ data->flow->type == FLOW_SHYPHEN || data->flow->type == FLOW_ANCHOR)
{
len = 0;
}