From 3028fbf00d2d571b6f67001b5c09c15e3e2cfa26 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 19 Dec 2011 15:19:40 +0000 Subject: More Memory squeezing fixes --- draw/draw_glyph.c | 14 +++++-- draw/draw_simple_scale.c | 58 ++++++++++++++------------ fitz/res_path.c | 10 +++-- fitz/res_pixmap.c | 19 +++++++-- fitz/res_text.c | 21 +++++++--- fitz/stm_read.c | 2 +- pdf/pdf_colorspace.c | 101 +++++++++++++++++++++++++++------------------ pdf/pdf_image.c | 3 +- pdf/pdf_interpret.c | 105 +++++++++++++++++++++++++++++------------------ 9 files changed, 209 insertions(+), 124 deletions(-) diff --git a/draw/draw_glyph.c b/draw/draw_glyph.c index 328b79f7..6b83af74 100644 --- a/draw/draw_glyph.c +++ b/draw/draw_glyph.c @@ -133,10 +133,18 @@ fz_render_glyph(fz_context *ctx, fz_glyph_cache *cache, fz_font *font, int gid, { if (cache->total + val->w * val->h > MAX_CACHE_SIZE) fz_evict_glyph_cache(ctx, cache); - fz_keep_font(key.font); - fz_hash_insert(cache->hash, &key, val); + fz_try(ctx) + { + fz_hash_insert(cache->hash, &key, val); + fz_keep_font(key.font); + val = fz_keep_pixmap(val); + } + fz_catch(ctx) + { + fz_warn(ctx, "Failed to encache glyph - continuing"); + } cache->total += val->w * val->h; - return fz_keep_pixmap(val); + return val; } return val; } diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c index cd8ac2b9..6c8e451d 100644 --- a/draw/draw_simple_scale.c +++ b/draw/draw_simple_scale.c @@ -1178,6 +1178,9 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa int dst_w_int, dst_h_int, dst_x_int, dst_y_int; int flip_x, flip_y; + fz_var(contrib_cols); + fz_var(contrib_rows); + DBUG(("Scale: (%d,%d) to (%g,%g) at (%g,%g)\n",src->w,src->h,w,h,x,y)); /* Find the destination bbox, width/height, and sub pixel offset, @@ -1240,35 +1243,30 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa DBUG(("Result image: (%d,%d) at (%d,%d) (subpix=%g,%g)\n", dst_w_int, dst_h_int, dst_x_int, dst_y_int, x, y)); - /* Step 1: Calculate the weights for columns and rows */ -#ifdef SINGLE_PIXEL_SPECIALS - if (src->w == 1) + fz_try(ctx) { - contrib_cols = NULL; - } - else + /* Step 1: Calculate the weights for columns and rows */ +#ifdef SINGLE_PIXEL_SPECIALS + if (src->w == 1) + contrib_cols = NULL; + else #endif /* SINGLE_PIXEL_SPECIALS */ - { - contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); - if (!contrib_cols) - goto cleanup; - } + contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); #ifdef SINGLE_PIXEL_SPECIALS - if (src->h == 1) - { - contrib_rows = NULL; - } - else + if (src->h == 1) + contrib_rows = NULL; + else #endif /* SINGLE_PIXEL_SPECIALS */ + contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); + + output = fz_new_pixmap(ctx, src->colorspace, dst_w_int, dst_h_int); + } + fz_catch(ctx) { - contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); - if (!contrib_rows) - goto cleanup; + fz_free(ctx, contrib_cols); + fz_free(ctx, contrib_rows); + fz_rethrow(ctx); } - - assert(!contrib_cols || contrib_cols->count == dst_w_int); - assert(!contrib_rows || contrib_rows->count == dst_h_int); - output = fz_new_pixmap(ctx, src->colorspace, dst_w_int, dst_h_int); output->x = dst_x_int; output->y = dst_y_int; @@ -1302,9 +1300,17 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa temp_rows = contrib_rows->max_len; if (temp_span <= 0 || temp_rows > INT_MAX / temp_span) goto cleanup; - temp = fz_calloc(ctx, temp_span*temp_rows, sizeof(unsigned char)); - if (!temp) - goto cleanup; + fz_try(ctx) + { + temp = fz_calloc(ctx, temp_span*temp_rows, sizeof(unsigned char)); + } + fz_catch(ctx) + { + fz_drop_pixmap(ctx, output); + fz_free(ctx, contrib_cols); + fz_free(ctx, contrib_rows); + fz_rethrow(ctx); + } switch (src->n) { default: diff --git a/fitz/res_path.c b/fitz/res_path.c index 054b3c1f..bf61cff6 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -49,11 +49,13 @@ fz_free_path(fz_context *ctx, fz_path *path) static void grow_path(fz_context *ctx, fz_path *path, int n) { - if (path->len + n < path->cap) + int newcap = path->cap; + if (path->len + n <= path->cap) return; - while (path->len + n > path->cap) - path->cap = path->cap + 36; - path->items = fz_resize_array(ctx, path->items, path->cap, sizeof(fz_path_item)); + while (path->len + n > newcap) + newcap = newcap + 36; + path->items = fz_resize_array(ctx, path->items, newcap, sizeof(fz_path_item)); + path->cap = newcap; } void diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index 99132a31..2ab95678 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -446,12 +446,17 @@ fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha) static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; FILE *fp; unsigned char head[13]; - unsigned char *udata, *cdata, *sp, *dp; + unsigned char *udata = NULL; + unsigned char *cdata = NULL; + unsigned char *sp, *dp; uLong usize, csize; int y, x, k, sn, dn; int color; int err; + fz_var(udata); + fz_var(cdata); + if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) fz_throw(ctx, "pixmap must be grayscale or rgb to write as png"); @@ -471,8 +476,16 @@ fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha) usize = (pixmap->w * dn + 1) * pixmap->h; csize = compressBound(usize); - udata = fz_malloc(ctx, usize); - cdata = fz_malloc(ctx, csize); + fz_try(ctx) + { + udata = fz_malloc(ctx, usize); + cdata = fz_malloc(ctx, csize); + } + fz_catch(ctx) + { + fz_free(ctx, udata); + fz_rethrow(ctx); + } sp = pixmap->samples; dp = udata; diff --git a/fitz/res_text.c b/fitz/res_text.c index b8c5c5fd..63338435 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -19,8 +19,11 @@ fz_new_text(fz_context *ctx, fz_font *font, fz_matrix trm, int wmode) void fz_free_text(fz_context *ctx, fz_text *text) { - fz_drop_font(ctx, text->font); - fz_free(ctx, text->items); + if (text != NULL) + { + fz_drop_font(ctx, text->font); + fz_free(ctx, text->items); + } fz_free(ctx, text); } @@ -30,13 +33,21 @@ fz_clone_text(fz_context *ctx, fz_text *old) fz_text *text; text = fz_malloc_struct(ctx, fz_text); + text->len = old->len; + fz_try(ctx) + { + text->items = fz_malloc_array(ctx, text->len, sizeof(fz_text_item)); + } + fz_catch(ctx) + { + fz_free(ctx, text); + fz_rethrow(ctx); + } + memcpy(text->items, old->items, text->len * sizeof(fz_text_item)); text->font = fz_keep_font(old->font); text->trm = old->trm; text->wmode = old->wmode; - text->len = old->len; text->cap = text->len; - text->items = fz_malloc_array(ctx, text->len, sizeof(fz_text_item)); - memcpy(text->items, old->items, text->len * sizeof(fz_text_item)); return text; } diff --git a/fitz/stm_read.c b/fitz/stm_read.c index 3d76d51a..2066b14c 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -90,7 +90,7 @@ fz_fill_buffer(fz_stream *stm) fz_buffer * fz_read_all(fz_stream *stm, int initial) { - fz_buffer *buf; + fz_buffer *buf = NULL; int n; fz_context *ctx = stm->ctx; diff --git a/pdf/pdf_colorspace.c b/pdf/pdf_colorspace.c index 9d2f87ed..b2f42b8f 100644 --- a/pdf/pdf_colorspace.c +++ b/pdf/pdf_colorspace.c @@ -220,63 +220,82 @@ pdf_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src) static fz_colorspace * load_indexed(pdf_xref *xref, fz_obj *array) { - struct indexed *idx; + struct indexed *idx = NULL; fz_context *ctx = xref->ctx; fz_obj *baseobj = fz_array_get(array, 1); fz_obj *highobj = fz_array_get(array, 2); fz_obj *lookup = fz_array_get(array, 3); - fz_colorspace *base, *cs; + fz_colorspace *base = NULL; + fz_colorspace *cs = NULL; int i, n; - base = pdf_load_colorspace(xref, baseobj); - /* "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj) */ - - idx = fz_malloc_struct(ctx, struct indexed); - idx->base = base; - idx->high = fz_to_int(highobj); - idx->high = CLAMP(idx->high, 0, 255); - n = base->n * (idx->high + 1); - idx->lookup = fz_malloc_array(ctx, 1, n); - - cs = fz_new_colorspace(ctx, "Indexed", 1); - cs->to_rgb = indexed_to_rgb; - cs->free_data = free_indexed; - cs->data = idx; - cs->size += sizeof(*idx) + n + (base ? base->size : 0); - - if (fz_is_string(lookup) && fz_to_str_len(lookup) == n) - { - unsigned char *buf = (unsigned char *) fz_to_str_buf(lookup); - for (i = 0; i < n; i++) - idx->lookup[i] = buf[i]; - } - else if (fz_is_indirect(lookup)) - { - fz_stream *file; + fz_var(idx); + fz_var(base); + fz_var(cs); - fz_try(ctx) + fz_try(ctx) + { + base = pdf_load_colorspace(xref, baseobj); + /* "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj) */ + + idx = fz_malloc_struct(ctx, struct indexed); + idx->lookup = NULL; + idx->base = base; + idx->high = fz_to_int(highobj); + idx->high = CLAMP(idx->high, 0, 255); + n = base->n * (idx->high + 1); + idx->lookup = fz_malloc_array(ctx, 1, n); + + cs = fz_new_colorspace(ctx, "Indexed", 1); + cs->to_rgb = indexed_to_rgb; + cs->free_data = free_indexed; + cs->data = idx; + cs->size += sizeof(*idx) + n + (base ? base->size : 0); + + if (fz_is_string(lookup) && fz_to_str_len(lookup) == n) { - file = pdf_open_stream(xref, fz_to_num(lookup), fz_to_gen(lookup)); + unsigned char *buf = (unsigned char *) fz_to_str_buf(lookup); + for (i = 0; i < n; i++) + idx->lookup[i] = buf[i]; } - fz_catch(ctx) + else if (fz_is_indirect(lookup)) { - fz_drop_colorspace(ctx, cs); - fz_throw(ctx, "cannot open colorspace lookup table (%d 0 R)", fz_to_num(lookup)); - } + fz_stream *file = NULL; + + fz_try(ctx) + { + file = pdf_open_stream(xref, fz_to_num(lookup), fz_to_gen(lookup)); + } + fz_catch(ctx) + { + fz_throw(ctx, "cannot open colorspace lookup table (%d 0 R)", fz_to_num(lookup)); + } + + i = fz_read(file, idx->lookup, n); + if (i < 0) + { + fz_close(file); + fz_throw(ctx, "cannot read colorspace lookup table (%d 0 R)", fz_to_num(lookup)); + } - i = fz_read(file, idx->lookup, n); - if (i < 0) + fz_close(file); + } + else { - fz_drop_colorspace(ctx, cs); - fz_throw(ctx, "cannot read colorspace lookup table (%d 0 R)", fz_to_num(lookup)); + fz_throw(ctx, "cannot parse colorspace lookup table"); } - - fz_close(file); } - else + fz_catch(ctx) { + if (cs == NULL || cs->data != idx) + { + fz_drop_colorspace(ctx, base); + if (idx) + fz_free(ctx, idx->lookup); + fz_free(ctx, idx); + } fz_drop_colorspace(ctx, cs); - fz_throw(ctx, "cannot parse colorspace lookup table"); + fz_rethrow(ctx); } return cs; diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c index ead5c365..db2c6cc4 100644 --- a/pdf/pdf_image.c +++ b/pdf/pdf_image.c @@ -166,7 +166,8 @@ pdf_load_image_imp(pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, i } fz_catch(ctx) { - fz_throw(ctx, "out of memory"); + fz_drop_colorspace(ctx, colorspace); + fz_rethrow(ctx); } if (colorspace) diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c index 0d5e2aa2..7fce1d52 100644 --- a/pdf/pdf_interpret.c +++ b/pdf/pdf_interpret.c @@ -1266,6 +1266,7 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr fz_matrix oldtopctm; int oldtop; int popmask; + int caught = 0; pdf_gsave(csi); @@ -1277,55 +1278,62 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr transform = fz_concat(xobj->matrix, transform); gstate->ctm = fz_concat(transform, gstate->ctm); - /* apply soft mask, create transparency group and reset state */ - if (xobj->transparency) + fz_try(ctx) { - if (gstate->softmask) + /* apply soft mask, create transparency group and reset state */ + if (xobj->transparency) { - pdf_xobject *softmask = gstate->softmask; - fz_rect bbox = fz_transform_rect(gstate->ctm, xobj->bbox); + if (gstate->softmask) + { + pdf_xobject *softmask = gstate->softmask; + fz_rect bbox = fz_transform_rect(gstate->ctm, xobj->bbox); - gstate->softmask = NULL; - popmask = 1; + gstate->softmask = NULL; + popmask = 1; - fz_begin_mask(csi->dev, bbox, gstate->luminosity, - softmask->colorspace, gstate->softmask_bc); - pdf_run_xobject(csi, resources, softmask, fz_identity); - /* RJW: "cannot run softmask" */ - fz_end_mask(csi->dev); + fz_begin_mask(csi->dev, bbox, gstate->luminosity, + softmask->colorspace, gstate->softmask_bc); + pdf_run_xobject(csi, resources, softmask, fz_identity); + /* RJW: "cannot run softmask" */ + fz_end_mask(csi->dev); - pdf_drop_xobject(ctx, softmask); - } + pdf_drop_xobject(ctx, softmask); + } - fz_begin_group(csi->dev, - fz_transform_rect(gstate->ctm, xobj->bbox), - xobj->isolated, xobj->knockout, gstate->blendmode, gstate->fill.alpha); + fz_begin_group(csi->dev, + fz_transform_rect(gstate->ctm, xobj->bbox), + xobj->isolated, xobj->knockout, gstate->blendmode, gstate->fill.alpha); - gstate->blendmode = 0; - gstate->stroke.alpha = 1; - gstate->fill.alpha = 1; - } + gstate->blendmode = 0; + gstate->stroke.alpha = 1; + gstate->fill.alpha = 1; + } - /* clip to the bounds */ + /* clip to the bounds */ - fz_moveto(ctx, csi->path, xobj->bbox.x0, xobj->bbox.y0); - fz_lineto(ctx, csi->path, xobj->bbox.x1, xobj->bbox.y0); - fz_lineto(ctx, csi->path, xobj->bbox.x1, xobj->bbox.y1); - fz_lineto(ctx, csi->path, xobj->bbox.x0, xobj->bbox.y1); - fz_closepath(ctx, csi->path); - csi->clip = 1; - pdf_show_path(csi, 0, 0, 0, 0); + fz_moveto(ctx, csi->path, xobj->bbox.x0, xobj->bbox.y0); + fz_lineto(ctx, csi->path, xobj->bbox.x1, xobj->bbox.y0); + fz_lineto(ctx, csi->path, xobj->bbox.x1, xobj->bbox.y1); + fz_lineto(ctx, csi->path, xobj->bbox.x0, xobj->bbox.y1); + fz_closepath(ctx, csi->path); + csi->clip = 1; + pdf_show_path(csi, 0, 0, 0, 0); - /* run contents */ + /* run contents */ - oldtopctm = csi->top_ctm; - csi->top_ctm = gstate->ctm; + oldtopctm = csi->top_ctm; + csi->top_ctm = gstate->ctm; - if (xobj->resources) - resources = xobj->resources; + if (xobj->resources) + resources = xobj->resources; - pdf_run_buffer(csi, resources, xobj->contents); - /* RJW: "cannot interpret XObject stream" */ + pdf_run_buffer(csi, resources, xobj->contents); + /* RJW: "cannot interpret XObject stream" */ + } + fz_catch(ctx) + { + caught = 1; + } csi->top_ctm = oldtopctm; @@ -1334,8 +1342,10 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr pdf_grestore(csi); - /* wrap up transparency stacks */ + if (caught) + fz_rethrow(ctx); + /* wrap up transparency stacks */ if (xobj->transparency) { fz_end_group(csi->dev); @@ -1671,8 +1681,15 @@ static void pdf_run_Do(pdf_csi *csi, fz_obj *rdb) if (!xobj->resources) xobj->resources = fz_keep_obj(rdb); - pdf_run_xobject(csi, xobj->resources, xobj, fz_identity); - /* RJW: "cannot draw xobject (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ + fz_try(ctx) + { + pdf_run_xobject(csi, xobj->resources, xobj, fz_identity); + } + fz_catch(ctx) + { + pdf_drop_xobject(ctx, xobj); + fz_throw(ctx, "cannot draw xobject (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + } pdf_drop_xobject(ctx, xobj); } @@ -1684,7 +1701,15 @@ static void pdf_run_Do(pdf_csi *csi, fz_obj *rdb) fz_pixmap *img; img = pdf_load_image(csi->xref, obj); /* RJW: "cannot load image (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ - pdf_show_image(csi, img); + fz_try(ctx) + { + pdf_show_image(csi, img); + } + fz_catch(ctx) + { + fz_drop_pixmap(ctx, img); + fz_rethrow(ctx); + } fz_drop_pixmap(ctx, img); } } -- cgit v1.2.3