diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-10-12 14:45:23 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-10-12 14:45:42 +0200 |
commit | 69c379990d83d83682b23eac3ddf390c0d85e976 (patch) | |
tree | c6d2fd66d472784924e524c95552aa41d6c87ce6 /source | |
parent | cf94c2a1e8cac52074183b31f75b71480dbdcea1 (diff) | |
download | mupdf-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')
-rw-r--r-- | source/fitz/pool.c | 8 | ||||
-rw-r--r-- | source/html/css-apply.c | 18 | ||||
-rw-r--r-- | source/html/css-parse.c | 182 | ||||
-rw-r--r-- | source/html/html-layout.c | 111 |
4 files changed, 153 insertions, 166 deletions
diff --git a/source/fitz/pool.c b/source/fitz/pool.c index e676947f..2591c563 100644 --- a/source/fitz/pool.c +++ b/source/fitz/pool.c @@ -31,6 +31,14 @@ void *fz_pool_alloc(fz_context *ctx, fz_pool *pool, size_t size) return ptr; } +char *fz_pool_strdup(fz_context *ctx, fz_pool *pool, const char *s) +{ + size_t n = strlen(s) + 1; + char *p = fz_pool_alloc(ctx, pool, n); + memcpy(p, s, n); + return p; +} + void fz_drop_pool(fz_context *ctx, fz_pool *pool) { fz_pool_node *node = pool->head; diff --git a/source/html/css-apply.c b/source/html/css-apply.c index d7375752..03e61a87 100644 --- a/source/html/css-apply.c +++ b/source/html/css-apply.c @@ -622,14 +622,14 @@ sort_properties(fz_css_match *match) } void -fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *css, fz_xml *node) +fz_match_css(fz_context *ctx, fz_css_match *match, fz_css *css, fz_xml *node) { fz_css_rule *rule; fz_css_selector *sel; fz_css_property *prop, *head, *tail; const char *s; - for (rule = css; rule; rule = rule->next) + for (rule = css->rule; rule; rule = rule->next) { sel = rule->selector; while (sel) @@ -649,16 +649,14 @@ fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *css, fz_xml *nod { fz_try(ctx) { - head = tail = prop = fz_parse_css_properties(ctx, s); + head = tail = prop = fz_parse_css_properties(ctx, css->pool, s); while (prop) { add_property(match, prop->name, prop->value, INLINE_SPECIFICITY); tail = prop; prop = prop->next; } - if (tail) - tail->next = css->garbage; - css->garbage = head; + /* We can "leak" the property here, since it is freed along with the pool allocator. */ } fz_catch(ctx) { @@ -670,13 +668,13 @@ fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *css, fz_xml *nod } void -fz_match_css_at_page(fz_context *ctx, fz_css_match *match, fz_css_rule *css) +fz_match_css_at_page(fz_context *ctx, fz_css_match *match, fz_css *css) { fz_css_rule *rule; fz_css_selector *sel; fz_css_property *prop; - for (rule = css; rule; rule = rule->next) + for (rule = css->rule; rule; rule = rule->next) { sel = rule->selector; while (sel) @@ -761,12 +759,12 @@ fz_add_css_font_face(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, co } void -fz_add_css_font_faces(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const char *base_uri, fz_css_rule *css) +fz_add_css_font_faces(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const char *base_uri, fz_css *css) { fz_css_rule *rule; fz_css_selector *sel; - for (rule = css; rule; rule = rule->next) + for (rule = css->rule; rule; rule = rule->next) { sel = rule->selector; while (sel) diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 7fd8571a..b5d436e8 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -3,6 +3,7 @@ struct lexbuf { fz_context *ctx; + fz_pool *pool; const unsigned char *s; const char *file; int line; @@ -20,20 +21,45 @@ FZ_NORETURN static void fz_css_error(struct lexbuf *buf, const char *msg) fz_throw(buf->ctx, FZ_ERROR_SYNTAX, "css syntax error: %s (%s:%d)", msg, buf->file, buf->line); } -static fz_css_rule *fz_new_css_rule(fz_context *ctx, fz_css_selector *selector, fz_css_property *declaration) +fz_css *fz_new_css(fz_context *ctx) { - fz_css_rule *rule = fz_malloc_struct(ctx, fz_css_rule); + fz_pool *pool = fz_new_pool(ctx); + fz_css *css; + + fz_try(ctx) + { + css = fz_pool_alloc(ctx, pool, sizeof *css); + css->pool = pool; + css->rule = NULL; + } + fz_catch(ctx) + { + fz_drop_pool(ctx, pool); + fz_rethrow(ctx); + } + + return css; +} + +void fz_drop_css(fz_context *ctx, fz_css *css) +{ + if (css) + fz_drop_pool(ctx, css->pool); +} + +static fz_css_rule *fz_new_css_rule(fz_context *ctx, fz_pool *pool, fz_css_selector *selector, fz_css_property *declaration) +{ + fz_css_rule *rule = fz_pool_alloc(ctx, pool, sizeof *rule); rule->selector = selector; rule->declaration = declaration; - rule->garbage = NULL; rule->next = NULL; return rule; } -static fz_css_selector *fz_new_css_selector(fz_context *ctx, const char *name) +static fz_css_selector *fz_new_css_selector(fz_context *ctx, fz_pool *pool, const char *name) { - fz_css_selector *sel = fz_malloc_struct(ctx, fz_css_selector); - sel->name = name ? fz_strdup(ctx, name) : NULL; + fz_css_selector *sel = fz_pool_alloc(ctx, pool, sizeof *sel); + sel->name = name ? fz_pool_strdup(ctx, pool, name) : NULL; sel->combine = 0; sel->cond = NULL; sel->left = NULL; @@ -42,20 +68,20 @@ static fz_css_selector *fz_new_css_selector(fz_context *ctx, const char *name) return sel; } -static fz_css_condition *fz_new_css_condition(fz_context *ctx, int type, const char *key, const char *val) +static fz_css_condition *fz_new_css_condition(fz_context *ctx, fz_pool *pool, int type, const char *key, const char *val) { - fz_css_condition *cond = fz_malloc_struct(ctx, fz_css_condition); + fz_css_condition *cond = fz_pool_alloc(ctx, pool, sizeof *cond); cond->type = type; - cond->key = key ? fz_strdup(ctx, key) : NULL; - cond->val = val ? fz_strdup(ctx, val) : NULL; + cond->key = key ? fz_pool_strdup(ctx, pool, key) : NULL; + cond->val = val ? fz_pool_strdup(ctx, pool, val) : NULL; cond->next = NULL; return cond; } -static fz_css_property *fz_new_css_property(fz_context *ctx, const char *name, fz_css_value *value, int spec) +static fz_css_property *fz_new_css_property(fz_context *ctx, fz_pool *pool, const char *name, fz_css_value *value, int spec) { - fz_css_property *prop = fz_malloc_struct(ctx, fz_css_property); - prop->name = fz_strdup(ctx, name); + fz_css_property *prop = fz_pool_alloc(ctx, pool, sizeof *prop); + prop->name = fz_pool_strdup(ctx, pool, name); prop->value = value; prop->spec = spec; prop->important = 0; @@ -63,9 +89,9 @@ static fz_css_property *fz_new_css_property(fz_context *ctx, const char *name, f return prop; } -static fz_css_value *fz_new_css_value_x(fz_context *ctx, int type) +static fz_css_value *fz_new_css_value_x(fz_context *ctx, fz_pool *pool, int type) { - fz_css_value *val = fz_malloc_struct(ctx, fz_css_value); + fz_css_value *val = fz_pool_alloc(ctx, pool, sizeof *val); val->type = type; val->data = NULL; val->args = NULL; @@ -73,79 +99,16 @@ static fz_css_value *fz_new_css_value_x(fz_context *ctx, int type) return val; } -static fz_css_value *fz_new_css_value(fz_context *ctx, int type, const char *data) +static fz_css_value *fz_new_css_value(fz_context *ctx, fz_pool *pool, int type, const char *data) { - fz_css_value *val = fz_malloc_struct(ctx, fz_css_value); + fz_css_value *val = fz_pool_alloc(ctx, pool, sizeof *val); val->type = type; - val->data = fz_strdup(ctx, data); + val->data = fz_pool_strdup(ctx, pool, data); val->args = NULL; val->next = NULL; return val; } -static void fz_drop_css_value(fz_context *ctx, fz_css_value *val) -{ - while (val) - { - fz_css_value *next = val->next; - fz_drop_css_value(ctx, val->args); - fz_free(ctx, val->data); - fz_free(ctx, val); - val = next; - } -} - -static void fz_drop_css_condition(fz_context *ctx, fz_css_condition *cond) -{ - while (cond) - { - fz_css_condition *next = cond->next; - fz_free(ctx, cond->key); - fz_free(ctx, cond->val); - fz_free(ctx, cond); - cond = next; - } -} - -static void fz_drop_css_selector(fz_context *ctx, fz_css_selector *sel) -{ - while (sel) - { - fz_css_selector *next = sel->next; - fz_free(ctx, sel->name); - fz_drop_css_condition(ctx, sel->cond); - fz_drop_css_selector(ctx, sel->left); - fz_drop_css_selector(ctx, sel->right); - fz_free(ctx, sel); - sel = next; - } -} - -static void fz_drop_css_property(fz_context *ctx, fz_css_property *prop) -{ - while (prop) - { - fz_css_property *next = prop->next; - fz_free(ctx, prop->name); - fz_drop_css_value(ctx, prop->value); - fz_free(ctx, prop); - prop = next; - } -} - -void fz_drop_css(fz_context *ctx, fz_css_rule *rule) -{ - while (rule) - { - fz_css_rule *next = rule->next; - fz_drop_css_selector(ctx, rule->selector); - fz_drop_css_property(ctx, rule->declaration); - fz_drop_css_property(ctx, rule->garbage); - fz_free(ctx, rule); - rule = next; - } -} - static void css_lex_next(struct lexbuf *buf) { buf->c = *(buf->s++); @@ -153,9 +116,10 @@ static void css_lex_next(struct lexbuf *buf) ++buf->line; } -static void css_lex_init(fz_context *ctx, struct lexbuf *buf, const char *s, const char *file) +static void css_lex_init(fz_context *ctx, struct lexbuf *buf, fz_pool *pool, const char *s, const char *file) { buf->ctx = ctx; + buf->pool = pool; buf->s = (const unsigned char *)s; buf->c = 0; buf->file = file; @@ -517,14 +481,14 @@ static fz_css_value *parse_term(struct lexbuf *buf) fz_css_error(buf, "expected number"); if (sign < 0) { - v = fz_new_css_value_x(buf->ctx, buf->lookahead); - v->data = fz_malloc(buf->ctx, strlen(buf->string) + 2); + v = fz_new_css_value_x(buf->ctx, buf->pool, buf->lookahead); + v->data = fz_pool_alloc(buf->ctx, buf->pool, strlen(buf->string) + 2); v->data[0] = '-'; strcpy(v->data + 1, buf->string); } else { - v = fz_new_css_value(buf->ctx, buf->lookahead, buf->string); + v = fz_new_css_value(buf->ctx, buf->pool, buf->lookahead, buf->string); } next(buf); white(buf); @@ -533,7 +497,7 @@ static fz_css_value *parse_term(struct lexbuf *buf) if (buf->lookahead == CSS_KEYWORD) { - v = fz_new_css_value(buf->ctx, CSS_KEYWORD, buf->string); + v = fz_new_css_value(buf->ctx, buf->pool, CSS_KEYWORD, buf->string); next(buf); if (accept(buf, '(')) { @@ -554,7 +518,7 @@ static fz_css_value *parse_term(struct lexbuf *buf) case CSS_NUMBER: case CSS_LENGTH: case CSS_PERCENT: - v = fz_new_css_value(buf->ctx, buf->lookahead, buf->string); + v = fz_new_css_value(buf->ctx, buf->pool, buf->lookahead, buf->string); next(buf); white(buf); return v; @@ -575,13 +539,13 @@ static fz_css_value *parse_expr(struct lexbuf *buf) if (accept(buf, ',')) { white(buf); - tail = tail->next = fz_new_css_value(buf->ctx, ',', ","); + tail = tail->next = fz_new_css_value(buf->ctx, buf->pool, ',', ","); tail = tail->next = parse_term(buf); } else if (accept(buf, '/')) { white(buf); - tail = tail->next = fz_new_css_value(buf->ctx, '/', "/"); + tail = tail->next = fz_new_css_value(buf->ctx, buf->pool, '/', "/"); tail = tail->next = parse_term(buf); } else @@ -599,7 +563,7 @@ static fz_css_property *parse_declaration(struct lexbuf *buf) if (buf->lookahead != CSS_KEYWORD) fz_css_error(buf, "expected keyword in property"); - p = fz_new_css_property(buf->ctx, buf->string, NULL, 0); + p = fz_new_css_property(buf->ctx, buf->pool, buf->string, NULL, 0); next(buf); white(buf); @@ -652,7 +616,7 @@ static char *parse_attrib_value(struct lexbuf *buf) if (buf->lookahead == CSS_KEYWORD || buf->lookahead == CSS_STRING) { - s = fz_strdup(buf->ctx, buf->string); + s = fz_pool_strdup(buf->ctx, buf->pool, buf->string); next(buf); white(buf); return s; @@ -670,7 +634,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) accept(buf, ':'); /* swallow css3 :: syntax and pretend it's a normal pseudo-class */ if (buf->lookahead != CSS_KEYWORD) fz_css_error(buf, "expected keyword after ':'"); - c = fz_new_css_condition(buf->ctx, ':', "pseudo", buf->string); + c = fz_new_css_condition(buf->ctx, buf->pool, ':', "pseudo", buf->string); next(buf); if (accept(buf, '(')) { @@ -686,7 +650,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) { if (buf->lookahead != CSS_KEYWORD) fz_css_error(buf, "expected keyword after '.'"); - c = fz_new_css_condition(buf->ctx, '.', "class", buf->string); + c = fz_new_css_condition(buf->ctx, buf->pool, '.', "class", buf->string); next(buf); return c; } @@ -697,7 +661,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) if (buf->lookahead != CSS_KEYWORD) fz_css_error(buf, "expected keyword after '['"); - c = fz_new_css_condition(buf->ctx, '[', buf->string, NULL); + c = fz_new_css_condition(buf->ctx, buf->pool, '[', buf->string, NULL); next(buf); white(buf); @@ -727,7 +691,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) if (buf->lookahead == CSS_HASH) { - c = fz_new_css_condition(buf->ctx, '#', "id", buf->string); + c = fz_new_css_condition(buf->ctx, buf->pool, '#', "id", buf->string); next(buf); return c; } @@ -753,14 +717,14 @@ static fz_css_selector *parse_simple_selector(struct lexbuf *buf) if (accept(buf, '*')) { - s = fz_new_css_selector(buf->ctx, NULL); + s = fz_new_css_selector(buf->ctx, buf->pool, NULL); if (iscond(buf->lookahead)) s->cond = parse_condition_list(buf); return s; } else if (buf->lookahead == CSS_KEYWORD) { - s = fz_new_css_selector(buf->ctx, buf->string); + s = fz_new_css_selector(buf->ctx, buf->pool, buf->string); next(buf); if (iscond(buf->lookahead)) s->cond = parse_condition_list(buf); @@ -768,7 +732,7 @@ static fz_css_selector *parse_simple_selector(struct lexbuf *buf) } else if (iscond(buf->lookahead)) { - s = fz_new_css_selector(buf->ctx, NULL); + s = fz_new_css_selector(buf->ctx, buf->pool, NULL); s->cond = parse_condition_list(buf); return s; } @@ -781,7 +745,7 @@ static fz_css_selector *parse_combinator(struct lexbuf *buf, int c, fz_css_selec fz_css_selector *sel, *b; white(buf); b = parse_simple_selector(buf); - sel = fz_new_css_selector(buf->ctx, NULL); + sel = fz_new_css_selector(buf->ctx, buf->pool, NULL); sel->combine = c; sel->left = a; sel->right = b; @@ -856,7 +820,7 @@ static fz_css_rule *parse_ruleset(struct lexbuf *buf) return NULL; } - return fz_new_css_rule(buf->ctx, s, p); + return fz_new_css_rule(buf->ctx, buf->pool, s, p); } static fz_css_rule *parse_at_page(struct lexbuf *buf) @@ -875,8 +839,8 @@ static fz_css_rule *parse_at_page(struct lexbuf *buf) expect(buf, '}'); white(buf); - s = fz_new_css_selector(buf->ctx, "@page"); - return fz_new_css_rule(buf->ctx, s, p); + s = fz_new_css_selector(buf->ctx, buf->pool, "@page"); + return fz_new_css_rule(buf->ctx, buf->pool, s, p); } static fz_css_rule *parse_at_font_face(struct lexbuf *buf) @@ -890,8 +854,8 @@ static fz_css_rule *parse_at_font_face(struct lexbuf *buf) expect(buf, '}'); white(buf); - s = fz_new_css_selector(buf->ctx, "@font-face"); - return fz_new_css_rule(buf->ctx, s, p); + s = fz_new_css_selector(buf->ctx, buf->pool, "@font-face"); + return fz_new_css_rule(buf->ctx, buf->pool, s, p); } static void parse_at_rule(struct lexbuf *buf) @@ -979,18 +943,18 @@ static fz_css_rule *parse_stylesheet(struct lexbuf *buf, fz_css_rule *chain) return chain ? chain : tail; } -fz_css_property *fz_parse_css_properties(fz_context *ctx, const char *source) +fz_css_property *fz_parse_css_properties(fz_context *ctx, fz_pool *pool, const char *source) { struct lexbuf buf; - css_lex_init(ctx, &buf, source, "<inline>"); + css_lex_init(ctx, &buf, pool, source, "<inline>"); next(&buf); return parse_declaration_list(&buf); } -fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source, const char *file) +void fz_parse_css(fz_context *ctx, fz_css *css, const char *source, const char *file) { struct lexbuf buf; - css_lex_init(ctx, &buf, source, file); + css_lex_init(ctx, &buf, css->pool, source, file); next(&buf); - return parse_stylesheet(&buf, chain); + css->rule = parse_stylesheet(&buf, css->rule); } 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; } |