summaryrefslogtreecommitdiff
path: root/source/html/html-layout.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-10-12 14:45:23 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-10-12 14:45:42 +0200
commit69c379990d83d83682b23eac3ddf390c0d85e976 (patch)
treec6d2fd66d472784924e524c95552aa41d6c87ce6 /source/html/html-layout.c
parentcf94c2a1e8cac52074183b31f75b71480dbdcea1 (diff)
downloadmupdf-69c379990d83d83682b23eac3ddf390c0d85e976.tar.xz
Use pool allocator when parsing CSS.
Fixes memory leaks when parsing throws exceptions and saves a lot of tiny mallocs for objects that have common life times.
Diffstat (limited to 'source/html/html-layout.c')
-rw-r--r--source/html/html-layout.c111
1 files changed, 64 insertions, 47 deletions
diff --git a/source/html/html-layout.c b/source/html/html-layout.c
index 34d6f8ac..fb039061 100644
--- a/source/html/html-layout.c
+++ b/source/html/html-layout.c
@@ -112,7 +112,7 @@ struct genstate
fz_tree *images;
int is_fb2;
const char *base_uri;
- fz_css_rule *css;
+ fz_css *css;
int at_bol;
int emit_white;
int last_brk_cls;
@@ -498,8 +498,11 @@ static void fz_drop_html_box(fz_context *ctx, fz_html_box *box)
void fz_drop_html(fz_context *ctx, fz_html *html)
{
- fz_drop_html_box(ctx, html->root);
- fz_drop_pool(ctx, html->pool);
+ if (html)
+ {
+ fz_drop_html_box(ctx, html->root);
+ fz_drop_pool(ctx, html->pool);
+ }
}
static fz_html_box *new_box(fz_context *ctx, fz_pool *pool, fz_bidi_direction markup_dir)
@@ -1907,8 +1910,8 @@ static char *concat_text(fz_context *ctx, fz_xml *root)
return s;
}
-static fz_css_rule *
-html_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rule *css, fz_xml *root)
+static void
+html_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css *css, fz_xml *root)
{
fz_xml *html, *head, *node;
fz_buffer *buf;
@@ -1942,7 +1945,7 @@ html_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rul
{
buf = fz_read_archive_entry(ctx, zip, path);
fz_write_buffer_byte(ctx, buf, 0);
- css = fz_parse_css(ctx, css, (char*)buf->data, path);
+ fz_parse_css(ctx, css, (char*)buf->data, path);
}
fz_always(ctx)
fz_drop_buffer(ctx, buf);
@@ -1956,17 +1959,16 @@ html_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rul
{
char *s = concat_text(ctx, node);
fz_try(ctx)
- css = fz_parse_css(ctx, css, s, "<style>");
+ fz_parse_css(ctx, css, s, "<style>");
fz_catch(ctx)
fz_warn(ctx, "ignoring inline stylesheet");
fz_free(ctx, s);
}
}
- return css;
}
-static fz_css_rule *
-fb2_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rule *css, fz_xml *root)
+static void
+fb2_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css *css, fz_xml *root)
{
fz_xml *fictionbook, *stylesheet;
@@ -1976,13 +1978,11 @@ fb2_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rule
{
char *s = concat_text(ctx, stylesheet);
fz_try(ctx)
- css = fz_parse_css(ctx, css, s, "<stylesheet>");
+ fz_parse_css(ctx, css, s, "<stylesheet>");
fz_catch(ctx)
fz_warn(ctx, "ignoring inline stylesheet");
fz_free(ctx, s);
}
-
- return css;
}
static fz_tree *
@@ -2321,11 +2321,12 @@ fz_html *
fz_parse_html(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const char *base_uri, fz_buffer *buf, const char *user_css)
{
fz_xml *xml;
- fz_css_match match;
fz_html *html;
+
+ fz_css_match match;
struct genstate g;
- g.pool = fz_new_pool(ctx);
+ g.pool = NULL;
g.set = set;
g.zip = zip;
g.base_uri = base_uri;
@@ -2335,46 +2336,62 @@ fz_parse_html(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const cha
xml = fz_parse_xml(ctx, buf->data, buf->len, 1);
- if (fz_xml_find(xml, "FictionBook"))
+ g.css = fz_new_css(ctx);
+ fz_try(ctx)
{
- g.is_fb2 = 1;
- g.css = fz_parse_css(ctx, NULL, fb2_default_css, "<default:fb2>");
- g.css = fb2_load_css(ctx, g.zip, g.base_uri, g.css, xml);
- g.images = load_fb2_images(ctx, xml);
+ if (fz_xml_find(xml, "FictionBook"))
+ {
+ g.is_fb2 = 1;
+ fz_parse_css(ctx, g.css, fb2_default_css, "<default:fb2>");
+ fb2_load_css(ctx, g.zip, g.base_uri, g.css, xml);
+ g.images = load_fb2_images(ctx, xml);
+ }
+ else
+ {
+ g.is_fb2 = 0;
+ fz_parse_css(ctx, g.css, html_default_css, "<default:html>");
+ html_load_css(ctx, g.zip, g.base_uri, g.css, xml);
+ g.images = NULL;
+ }
+
+ if (user_css)
+ fz_parse_css(ctx, g.css, user_css, "<user>");
+
+ fz_add_css_font_faces(ctx, g.set, g.zip, g.base_uri, g.css); /* load @font-face fonts into font set */
}
- else
+ fz_catch(ctx)
{
- g.is_fb2 = 0;
- g.css = fz_parse_css(ctx, NULL, html_default_css, "<default:html>");
- g.css = html_load_css(ctx, g.zip, g.base_uri, g.css, xml);
- g.images = NULL;
+ fz_warn(ctx, "ignoring styles due to errors: %s", fz_caught_message(ctx));
}
- if (user_css)
- g.css = fz_parse_css(ctx, g.css, user_css, "<user>");
-
- // print_rules(g.css);
-
- fz_add_css_font_faces(ctx, g.set, g.zip, g.base_uri, g.css); /* load @font-face fonts into font set */
-
- html = fz_malloc_struct(ctx, fz_html);
- html->pool = g.pool;
- html->root = new_box(ctx, g.pool, DEFAULT_DIR);
-
- match.up = NULL;
- match.count = 0;
- fz_match_css_at_page(ctx, &match, g.css);
- fz_apply_css_style(ctx, g.set, &html->root->style, &match);
- // TODO: transfer page margins out of this hacky box
-
- generate_boxes(ctx, xml, html->root, &match, 0, DEFAULT_DIR, FZ_LANG_UNSET, &g);
+ g.pool = fz_new_pool(ctx);
+ fz_try(ctx)
+ {
+ html = fz_pool_alloc(ctx, g.pool, sizeof *html);
+ html->pool = g.pool;
+ html->root = new_box(ctx, g.pool, DEFAULT_DIR);
- fz_drop_css(ctx, g.css);
- fz_drop_xml(ctx, xml);
+ match.up = NULL;
+ match.count = 0;
+ fz_match_css_at_page(ctx, &match, g.css);
+ fz_apply_css_style(ctx, g.set, &html->root->style, &match);
+ // TODO: transfer page margins out of this hacky box
- detect_directionality(ctx, g.pool, html->root);
+ generate_boxes(ctx, xml, html->root, &match, 0, DEFAULT_DIR, FZ_LANG_UNSET, &g);
- fz_drop_tree(ctx, g.images, (void(*)(fz_context*,void*))fz_drop_image);
+ detect_directionality(ctx, g.pool, html->root);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_css(ctx, g.css);
+ fz_drop_xml(ctx, xml);
+ fz_drop_tree(ctx, g.images, (void(*)(fz_context*,void*))fz_drop_image);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_pool(ctx, g.pool);
+ fz_rethrow(ctx);
+ }
return html;
}