summaryrefslogtreecommitdiff
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
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.
-rw-r--r--include/mupdf/fitz/pool.h1
-rw-r--r--include/mupdf/html.h21
-rw-r--r--source/fitz/pool.c8
-rw-r--r--source/html/css-apply.c18
-rw-r--r--source/html/css-parse.c182
-rw-r--r--source/html/html-layout.c111
6 files changed, 168 insertions, 173 deletions
diff --git a/include/mupdf/fitz/pool.h b/include/mupdf/fitz/pool.h
index 924fb804..919b08d0 100644
--- a/include/mupdf/fitz/pool.h
+++ b/include/mupdf/fitz/pool.h
@@ -21,6 +21,7 @@ struct fz_pool_node_s
fz_pool *fz_new_pool(fz_context *ctx);
void *fz_pool_alloc(fz_context *ctx, fz_pool *pool, size_t size);
+char *fz_pool_strdup(fz_context *ctx, fz_pool *pool, const char *s);
void fz_drop_pool(fz_context *ctx, fz_pool *pool);
#endif
diff --git a/include/mupdf/html.h b/include/mupdf/html.h
index 7c3eadac..f9bd4d98 100644
--- a/include/mupdf/html.h
+++ b/include/mupdf/html.h
@@ -9,6 +9,7 @@ typedef struct fz_html_s fz_html;
typedef struct fz_html_box_s fz_html_box;
typedef struct fz_html_flow_s fz_html_flow;
+typedef struct fz_css_s fz_css;
typedef struct fz_css_rule_s fz_css_rule;
typedef struct fz_css_match_prop_s fz_css_match_prop;
typedef struct fz_css_match_s fz_css_match;
@@ -48,11 +49,16 @@ enum
CSS_URI,
};
+struct fz_css_s
+{
+ fz_pool *pool;
+ fz_css_rule *rule;
+};
+
struct fz_css_rule_s
{
fz_css_selector *selector;
fz_css_property *declaration;
- fz_css_property *garbage; /* for freeing inline style attributes at the end */
fz_css_rule *next;
};
@@ -244,12 +250,13 @@ struct fz_html_flow_s
fz_html_flow *next;
};
-fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source, const char *file);
-fz_css_property *fz_parse_css_properties(fz_context *ctx, const char *source);
-void fz_drop_css(fz_context *ctx, fz_css_rule *rule);
+fz_css *fz_new_css(fz_context *ctx);
+void fz_parse_css(fz_context *ctx, fz_css *css, const char *source, const char *file);
+fz_css_property *fz_parse_css_properties(fz_context *ctx, fz_pool *pool, const char *source);
+void fz_drop_css(fz_context *ctx, fz_css *css);
-void fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *rule, fz_xml *node);
-void fz_match_css_at_page(fz_context *ctx, fz_css_match *match, fz_css_rule *css);
+void fz_match_css(fz_context *ctx, fz_css_match *match, fz_css *css, fz_xml *node);
+void fz_match_css_at_page(fz_context *ctx, fz_css_match *match, fz_css *css);
int fz_get_css_match_display(fz_css_match *node);
void fz_default_css_style(fz_context *ctx, fz_css_style *style);
@@ -264,7 +271,7 @@ void fz_add_html_font_face(fz_context *ctx, fz_html_font_set *set,
fz_font *fz_load_html_font(fz_context *ctx, fz_html_font_set *set, const char *family, int is_bold, int is_italic);
void fz_drop_html_font_set(fz_context *ctx, fz_html_font_set *htx);
-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);
+void fz_add_css_font_faces(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const char *base_uri, fz_css *css);
fz_html *fz_parse_html(fz_context *ctx, fz_html_font_set *htx, fz_archive *zip, const char *base_uri, fz_buffer *buf, const char *user_css);
void fz_layout_html(fz_context *ctx, fz_html *html, float w, float h, float em);
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;
}