summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2011-12-14 19:08:56 +0000
committerRobin Watts <robin.watts@artifex.com>2011-12-15 00:43:24 +0000
commit313e8f82816c839b3de47e1137a91414bb95a327 (patch)
treef680cd6ebc26e51dab5cd0b9a5337ce49197f6ac /pdf
parent09c8ebeea83f11ccac07bad76e516460e2c8e0f7 (diff)
downloadmupdf-313e8f82816c839b3de47e1137a91414bb95a327.tar.xz
Rework pdf_store to fz_store, a part of fz_context.
Firstly, we rename pdf_store to fz_store, reflecting the fact that there are no pdf specific dependencies on it. Next, we rework it so that all the objects that can be stored in the store start with an fz_storable structure. This consists of a reference count, and a function used to free the object when the reference count reaches zero. All the keep/drop functions are then reimplemented by calling fz_keep_sharable/fz_drop_sharable. The 'drop' functions as supplied by the callers are thus now 'free' functions, only called if the reference count drops to 0. The store changes to keep all the items in the store in the linked list (which becomes a doubly linked one). We still make use of the hashtable to index into this list quickly, but we now have the objects in an LRU ordering within the list. Every object is put into the store, with a size record; this is an estimate of how much memory would be freed by freeing that object. The store is moved into the context and given a maximum size; when new things are inserted into the store, care is taken to ensure that we do not expand beyond this size. We evict any stored items (that are not in use) starting from the least recently used. Finding an object in the store now takes a reference to it already. LOCK and UNLOCK comments are used to indicate where locks need to be taken and released to ensure thread safety.
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf.h32
-rw-r--r--pdf/pdf_cmap.c31
-rw-r--r--pdf/pdf_cmap_load.c20
-rw-r--r--pdf/pdf_colorspace.c10
-rw-r--r--pdf/pdf_font.c54
-rw-r--r--pdf/pdf_function.c69
-rw-r--r--pdf/pdf_image.c6
-rw-r--r--pdf/pdf_metrics.c2
-rw-r--r--pdf/pdf_page.c4
-rw-r--r--pdf/pdf_pattern.c60
-rw-r--r--pdf/pdf_shade.c16
-rw-r--r--pdf/pdf_store.c224
-rw-r--r--pdf/pdf_type3.c3
-rw-r--r--pdf/pdf_unicode.c2
-rw-r--r--pdf/pdf_xobject.c64
-rw-r--r--pdf/pdf_xref.c3
16 files changed, 214 insertions, 386 deletions
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index 79560dab..890e9f8b 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -90,8 +90,6 @@ struct pdf_xref_s
fz_obj **page_objs;
fz_obj **page_refs;
- struct pdf_store_s *store;
-
char scratch[65536];
};
@@ -154,24 +152,6 @@ unsigned char *pdf_get_crypt_key(pdf_xref *xref);
void pdf_debug_crypt(pdf_crypt *crypt);
/*
- * Resource store
- */
-
-typedef struct pdf_store_s pdf_store;
-
-pdf_store *pdf_new_store(fz_context *ctx);
-void pdf_free_store(fz_context *ctx, pdf_store *store);
-void pdf_debug_store(fz_context *ctx, pdf_store *store);
-
-typedef void *(pdf_store_keep_fn)(void *);
-typedef void (pdf_store_drop_fn)(fz_context *, void *);
-
-void pdf_store_item(fz_context *ctx, pdf_store *store, pdf_store_keep_fn *keepfn, pdf_store_drop_fn *dropfn, fz_obj *key, void *val);
-void *pdf_find_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *dropfn, fz_obj *key);
-void pdf_remove_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *dropfn, fz_obj *key);
-void pdf_age_store(fz_context *ctx, pdf_store *store, int maxage);
-
-/*
* Functions, Colorspaces, Shadings and Images
*/
@@ -181,6 +161,7 @@ pdf_function *pdf_load_function(pdf_xref *xref, fz_obj *ref);
void pdf_eval_function(fz_context *ctx, pdf_function *func, float *in, int inlen, float *out, int outlen);
pdf_function *pdf_keep_function(pdf_function *func);
void pdf_drop_function(fz_context *ctx, pdf_function *func);
+unsigned int pdf_function_size(pdf_function *func);
fz_colorspace *pdf_load_colorspace(pdf_xref *xref, fz_obj *obj);
fz_pixmap *pdf_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src);
@@ -199,7 +180,7 @@ typedef struct pdf_pattern_s pdf_pattern;
struct pdf_pattern_s
{
- int refs;
+ fz_storable storable;
int ismask;
float xstep;
float ystep;
@@ -221,7 +202,7 @@ typedef struct pdf_xobject_s pdf_xobject;
struct pdf_xobject_s
{
- int refs;
+ fz_storable storable;
fz_matrix matrix;
fz_rect bbox;
int isolated;
@@ -257,7 +238,7 @@ struct pdf_range_s
struct pdf_cmap_s
{
- int refs;
+ fz_storable storable;
char cmap_name[32];
char usecmap_name[32];
@@ -283,6 +264,8 @@ struct pdf_cmap_s
pdf_cmap *pdf_new_cmap(fz_context *ctx);
pdf_cmap *pdf_keep_cmap(pdf_cmap *cmap);
void pdf_drop_cmap(fz_context *ctx, pdf_cmap *cmap);
+void pdf_free_cmap_imp(fz_context *ctx, void *cmap);
+unsigned int pdf_cmap_size(pdf_cmap *cmap);
void pdf_debug_cmap(pdf_cmap *cmap);
int pdf_get_wmode(pdf_cmap *cmap);
@@ -356,7 +339,8 @@ struct pdf_vmtx_s
struct pdf_font_desc_s
{
- int refs;
+ fz_storable storable;
+ unsigned int size;
fz_font *font;
diff --git a/pdf/pdf_cmap.c b/pdf/pdf_cmap.c
index 8ae40fc5..b92f616e 100644
--- a/pdf/pdf_cmap.c
+++ b/pdf/pdf_cmap.c
@@ -30,13 +30,24 @@
* Allocate, destroy and simple parameters.
*/
+void
+pdf_free_cmap_imp(fz_context *ctx, void *cmap_)
+{
+ pdf_cmap *cmap = (pdf_cmap *)cmap_;
+ if (cmap->usecmap)
+ pdf_drop_cmap(ctx, cmap->usecmap);
+ fz_free(ctx, cmap->ranges);
+ fz_free(ctx, cmap->table);
+ fz_free(ctx, cmap);
+}
+
pdf_cmap *
pdf_new_cmap(fz_context *ctx)
{
pdf_cmap *cmap;
cmap = fz_malloc(ctx, sizeof(pdf_cmap));
- cmap->refs = 1;
+ FZ_INIT_STORABLE(cmap, 1, pdf_free_cmap_imp);
strcpy(cmap->cmap_name, "");
strcpy(cmap->usecmap_name, "");
@@ -55,28 +66,18 @@ pdf_new_cmap(fz_context *ctx)
return cmap;
}
+/* Could be a macro for speed */
pdf_cmap *
pdf_keep_cmap(pdf_cmap *cmap)
{
- if (cmap->refs >= 0)
- cmap->refs ++;
- return cmap;
+ return (pdf_cmap *)fz_keep_storable(&cmap->storable);
}
+/* Could be a macro for speed */
void
pdf_drop_cmap(fz_context *ctx, pdf_cmap *cmap)
{
- if (cmap->refs >= 0)
- {
- if (--cmap->refs == 0)
- {
- if (cmap->usecmap)
- pdf_drop_cmap(ctx, cmap->usecmap);
- fz_free(ctx, cmap->ranges);
- fz_free(ctx, cmap->table);
- fz_free(ctx, cmap);
- }
- }
+ fz_drop_storable(ctx, &cmap->storable);
}
void
diff --git a/pdf/pdf_cmap_load.c b/pdf/pdf_cmap_load.c
index 5bcf578f..51949907 100644
--- a/pdf/pdf_cmap_load.c
+++ b/pdf/pdf_cmap_load.c
@@ -1,6 +1,17 @@
#include "fitz.h"
#include "mupdf.h"
+unsigned int
+pdf_cmap_size(pdf_cmap *cmap)
+{
+ if (cmap == NULL)
+ return 0;
+ if (cmap->storable.refs < 0)
+ return 0;
+
+ return cmap->rcap * sizeof(pdf_range) + cmap->tcap * sizeof(short) + pdf_cmap_size(cmap->usecmap);
+}
+
/*
* Load CMap stream in PDF file
*/
@@ -13,11 +24,12 @@ pdf_load_embedded_cmap(pdf_xref *xref, fz_obj *stmobj)
fz_obj *wmode;
fz_obj *obj;
fz_context *ctx = xref->ctx;
- volatile int phase = 0;
+ int phase = 0;
+
+ fz_var(phase);
- if ((cmap = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_cmap, stmobj)))
+ if ((cmap = fz_find_item(ctx, pdf_free_cmap_imp, stmobj)))
{
- pdf_keep_cmap(cmap);
return cmap;
}
@@ -49,7 +61,7 @@ pdf_load_embedded_cmap(pdf_xref *xref, fz_obj *stmobj)
pdf_drop_cmap(ctx, usecmap);
}
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_cmap, (pdf_store_drop_fn *)pdf_drop_cmap, stmobj, cmap);
+ fz_store_item(ctx, stmobj, cmap, pdf_cmap_size(cmap));
}
fz_catch(ctx)
{
diff --git a/pdf/pdf_colorspace.c b/pdf/pdf_colorspace.c
index c386b34c..9edc1e90 100644
--- a/pdf/pdf_colorspace.c
+++ b/pdf/pdf_colorspace.c
@@ -61,7 +61,7 @@ rgb_to_lab(fz_context *ctx, fz_colorspace *cs, float *rgb, float *lab)
lab[2] = rgb[2];
}
-static fz_colorspace k_device_lab = { -1, "Lab", 3, lab_to_rgb, rgb_to_lab };
+static fz_colorspace k_device_lab = { {-1, fz_free_colorspace_imp}, 0, "Lab", 3, lab_to_rgb, rgb_to_lab };
static fz_colorspace *fz_device_lab = &k_device_lab;
/* Separation and DeviceN */
@@ -126,6 +126,7 @@ load_separation(pdf_xref *xref, fz_obj *array)
cs->to_rgb = separation_to_rgb;
cs->free_data = free_separation;
cs->data = sep;
+ cs->size += sizeof(struct separation) + (base ? base->size : 0) + pdf_function_size(tint);
return cs;
}
@@ -228,6 +229,7 @@ load_indexed(pdf_xref *xref, fz_obj *array)
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)
{
@@ -361,15 +363,15 @@ pdf_load_colorspace(pdf_xref *xref, fz_obj *obj)
fz_context *ctx = xref->ctx;
fz_colorspace *cs;
- if ((cs = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)fz_drop_colorspace, obj)))
+ if ((cs = fz_find_item(ctx, fz_free_colorspace_imp, obj)))
{
- return fz_keep_colorspace(cs);
+ return cs;
}
cs = pdf_load_colorspace_imp(xref, obj);
/* RJW: "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)fz_keep_colorspace, (pdf_store_drop_fn *)fz_drop_colorspace, obj, cs);
+ fz_store_item(ctx, obj, cs, cs->size);
return cs;
}
diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c
index dfd4782c..ae24df0f 100644
--- a/pdf/pdf_font.c
+++ b/pdf/pdf_font.c
@@ -198,6 +198,7 @@ pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, int mono, int
fz_throw(ctx, "cannot find substitute font");
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0);
+ fontdesc->size += len;
/* RJW: "cannot load freetype font from memory" */
fontdesc->font->ft_substitute = 1;
@@ -216,6 +217,7 @@ pdf_load_substitute_cjk_font(fz_context *ctx, pdf_font_desc *fontdesc, int ros,
fz_throw(ctx, "cannot find builtin CJK font");
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0);
+ fontdesc->size += len;
/* RJW: "cannot load builtin CJK font" */
fontdesc->font->ft_substitute = 1;
@@ -288,6 +290,7 @@ pdf_load_embedded_font(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *stmref)
fz_drop_buffer(ctx, buf);
fz_throw(ctx, "cannot load embedded font (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref));
}
+ fontdesc->size += buf->len;
/* save the buffer so we can free it later */
fontdesc->font->ft_data = buf->data;
@@ -304,29 +307,31 @@ pdf_load_embedded_font(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *stmref)
pdf_font_desc *
pdf_keep_font(pdf_font_desc *fontdesc)
{
- fontdesc->refs ++;
- return fontdesc;
+ return (pdf_font_desc *)fz_keep_storable(&fontdesc->storable);
}
void
pdf_drop_font(fz_context *ctx, pdf_font_desc *fontdesc)
{
- if (fontdesc && --fontdesc->refs == 0)
- {
- if (fontdesc->font)
- fz_drop_font(ctx, fontdesc->font);
- if (fontdesc->encoding)
- pdf_drop_cmap(ctx, fontdesc->encoding);
- if (fontdesc->to_ttf_cmap)
- pdf_drop_cmap(ctx, fontdesc->to_ttf_cmap);
- if (fontdesc->to_unicode)
- pdf_drop_cmap(ctx, fontdesc->to_unicode);
- fz_free(ctx, fontdesc->cid_to_gid);
- fz_free(ctx, fontdesc->cid_to_ucs);
- fz_free(ctx, fontdesc->hmtx);
- fz_free(ctx, fontdesc->vmtx);
- fz_free(ctx, fontdesc);
- }
+ fz_drop_storable(ctx, &fontdesc->storable);
+}
+
+static void
+pdf_free_font_imp(fz_context *ctx, pdf_font_desc *fontdesc)
+{
+ if (fontdesc->font)
+ fz_drop_font(ctx, fontdesc->font);
+ if (fontdesc->encoding)
+ pdf_drop_cmap(ctx, fontdesc->encoding);
+ if (fontdesc->to_ttf_cmap)
+ pdf_drop_cmap(ctx, fontdesc->to_ttf_cmap);
+ if (fontdesc->to_unicode)
+ pdf_drop_cmap(ctx, fontdesc->to_unicode);
+ fz_free(ctx, fontdesc->cid_to_gid);
+ fz_free(ctx, fontdesc->cid_to_ucs);
+ fz_free(ctx, fontdesc->hmtx);
+ fz_free(ctx, fontdesc->vmtx);
+ fz_free(ctx, fontdesc);
}
pdf_font_desc *
@@ -335,7 +340,8 @@ pdf_new_font_desc(fz_context *ctx)
pdf_font_desc *fontdesc;
fontdesc = fz_malloc(ctx, sizeof(pdf_font_desc));
- fontdesc->refs = 1;
+ FZ_INIT_STORABLE(fontdesc, 1, pdf_free_font_imp);
+ fontdesc->size = sizeof(pdf_font_desc);
fontdesc->font = NULL;
@@ -497,6 +503,7 @@ pdf_load_simple_font(pdf_xref *xref, fz_obj *dict)
fz_warn(ctx, "freetype could not find any cmaps");
etable = fz_malloc_array(ctx, 256, sizeof(unsigned short));
+ fontdesc->size += 256 * sizeof(unsigned short);
for (i = 0; i < 256; i++)
{
estrings[i] = NULL;
@@ -637,6 +644,7 @@ pdf_load_simple_font(pdf_xref *xref, fz_obj *dict)
}
fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
+ fontdesc->size += pdf_cmap_size(fontdesc->encoding);
fontdesc->cid_to_gid_len = 256;
fontdesc->cid_to_gid = etable;
@@ -771,6 +779,7 @@ load_cid_font(pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *to_unicode
{
fz_throw(ctx, "syntaxerror: font missing encoding");
}
+ fontdesc->size += pdf_cmap_size(fontdesc->encoding);
pdf_set_font_wmode(fontdesc, pdf_get_wmode(fontdesc->encoding));
@@ -787,6 +796,7 @@ load_cid_font(pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *to_unicode
fontdesc->cid_to_gid_len = (buf->len) / 2;
fontdesc->cid_to_gid = fz_malloc_array(ctx, fontdesc->cid_to_gid_len, sizeof(unsigned short));
+ fontdesc->size += fontdesc->cid_to_gid_len * sizeof(unsigned short);
for (i = 0; i < fontdesc->cid_to_gid_len; i++)
fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1];
@@ -1040,6 +1050,7 @@ pdf_make_width_table(fz_context *ctx, pdf_font_desc *fontdesc)
font->width_count ++;
font->width_table = fz_malloc_array(ctx, font->width_count, sizeof(int));
+ fontdesc->size += font->width_count * sizeof(int);
for (i = 0; i < fontdesc->hmtx_len; i++)
{
@@ -1062,9 +1073,8 @@ pdf_load_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
fz_context *ctx = xref->ctx;
pdf_font_desc *fontdesc;
- if ((fontdesc = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_font, dict)))
+ if ((fontdesc = fz_find_item(ctx, pdf_free_font_imp, dict)))
{
- pdf_keep_font(fontdesc);
return fontdesc;
}
@@ -1103,7 +1113,7 @@ pdf_load_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
if (fontdesc->font->ft_substitute && !fontdesc->to_ttf_cmap)
pdf_make_width_table(ctx, fontdesc);
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_font, (pdf_store_drop_fn *)pdf_drop_font, dict, fontdesc);
+ fz_store_item(ctx, dict, fontdesc, fontdesc->size);
return fontdesc;
}
diff --git a/pdf/pdf_function.c b/pdf/pdf_function.c
index fcd683ae..26d4bcec 100644
--- a/pdf/pdf_function.c
+++ b/pdf/pdf_function.c
@@ -19,7 +19,8 @@ enum
struct pdf_function_s
{
- int refs;
+ fz_storable storable;
+ unsigned int size;
int type; /* 0=sample 2=exponential 3=stitching 4=postscript */
int m; /* number of input values */
int n; /* number of output values */
@@ -849,6 +850,8 @@ load_postscript_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num,
fz_throw(ctx, "cannot parse calculator function (%d %d R)", num, gen);
}
+ func->size += func->u.p.cap * sizeof(psobj);
+
fz_close(stream);
}
@@ -947,6 +950,7 @@ load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int
samplecount *= func->u.sa.size[i];
func->u.sa.samples = fz_malloc_array(ctx, samplecount, sizeof(float));
+ func->size += samplecount * sizeof(float);
stream = pdf_open_stream(xref, num, gen);
/* RJW: "cannot open samples stream (%d %d R)", num, gen */
@@ -1198,6 +1202,7 @@ load_stitching_func(pdf_function *func, pdf_xref *xref, fz_obj *dict)
/* RJW: "cannot load sub function %d (%d %d R)", i, fz_to_num(sub), fz_to_gen(sub) */
if (funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n)
fz_throw(ctx, "sub function %d /Domain or /Range mismatch", i);
+ func->size += pdf_function_size(funcs[i]);
func->u.st.k ++;
}
@@ -1292,36 +1297,46 @@ eval_stitching_func(fz_context *ctx, pdf_function *func, float in, float *out)
pdf_function *
pdf_keep_function(pdf_function *func)
{
- func->refs ++;
- return func;
+ return (pdf_function *)fz_keep_storable(&func->storable);
}
void
pdf_drop_function(fz_context *ctx, pdf_function *func)
{
+ fz_drop_storable(ctx, &func->storable);
+}
+
+static void
+pdf_free_function_imp(fz_context *ctx, void *func_)
+{
+ pdf_function *func = (pdf_function *)func_;
int i;
- if (--func->refs == 0)
+
+ switch(func->type)
{
- switch(func->type)
- {
- case SAMPLE:
- fz_free(ctx, func->u.sa.samples);
- break;
- case EXPONENTIAL:
- break;
- case STITCHING:
- for (i = 0; i < func->u.st.k; i++)
- pdf_drop_function(ctx, func->u.st.funcs[i]);
- fz_free(ctx, func->u.st.funcs);
- fz_free(ctx, func->u.st.bounds);
- fz_free(ctx, func->u.st.encode);
- break;
- case POSTSCRIPT:
- fz_free(ctx, func->u.p.code);
- break;
- }
- fz_free(ctx, func);
+ case SAMPLE:
+ fz_free(ctx, func->u.sa.samples);
+ break;
+ case EXPONENTIAL:
+ break;
+ case STITCHING:
+ for (i = 0; i < func->u.st.k; i++)
+ pdf_drop_function(ctx, func->u.st.funcs[i]);
+ fz_free(ctx, func->u.st.funcs);
+ fz_free(ctx, func->u.st.bounds);
+ fz_free(ctx, func->u.st.encode);
+ break;
+ case POSTSCRIPT:
+ fz_free(ctx, func->u.p.code);
+ break;
}
+ fz_free(ctx, func);
+}
+
+unsigned int
+pdf_function_size(pdf_function *func)
+{
+ return (func ? func->size : 0);
}
pdf_function *
@@ -1332,15 +1347,15 @@ pdf_load_function(pdf_xref *xref, fz_obj *dict)
fz_obj *obj;
int i;
- if ((func = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_function, dict)))
+ if ((func = fz_find_item(ctx, pdf_free_function_imp, dict)))
{
- pdf_keep_function(func);
return func;
}
func = fz_malloc(ctx, sizeof(pdf_function));
memset(func, 0, sizeof *func);
- func->refs = 1;
+ FZ_INIT_STORABLE(func, 1, pdf_free_function_imp);
+ func->size = sizeof(*func);
obj = fz_dict_gets(dict, "FunctionType");
func->type = fz_to_int(obj);
@@ -1414,7 +1429,7 @@ pdf_load_function(pdf_xref *xref, fz_obj *dict)
"unknown")))), fz_to_num(dict), fz_to_gen(dict));
}
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_function, (pdf_store_drop_fn *)pdf_drop_function, dict, func);
+ fz_store_item(ctx, dict, func, func->size);
return func;
}
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c
index 3af9c5f8..4266ded3 100644
--- a/pdf/pdf_image.c
+++ b/pdf/pdf_image.c
@@ -364,15 +364,15 @@ pdf_load_image(pdf_xref *xref, fz_obj *dict)
fz_context *ctx = xref->ctx;
fz_pixmap *pix;
- if ((pix = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)fz_drop_pixmap, dict)))
+ if ((pix = fz_find_item(ctx, fz_free_pixmap_imp, dict)))
{
- return fz_keep_pixmap(pix);
+ return pix;
}
pix = pdf_load_image_imp(xref, NULL, dict, NULL, 0);
/* RJW: "cannot load image (%d 0 R)", fz_to_num(dict) */
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)fz_keep_pixmap, (pdf_store_drop_fn *)fz_drop_pixmap, dict, pix);
+ fz_store_item(ctx, dict, pix, fz_pixmap_size(pix));
return pix;
}
diff --git a/pdf/pdf_metrics.c b/pdf/pdf_metrics.c
index 3aa0ef24..ae6383eb 100644
--- a/pdf/pdf_metrics.c
+++ b/pdf/pdf_metrics.c
@@ -72,6 +72,7 @@ pdf_end_hmtx(pdf_font_desc *font)
if (!font->hmtx)
return;
qsort(font->hmtx, font->hmtx_len, sizeof(pdf_hmtx), cmph);
+ font->size += font->hmtx_cap * sizeof(pdf_hmtx);
}
void
@@ -80,6 +81,7 @@ pdf_end_vmtx(pdf_font_desc *font)
if (!font->vmtx)
return;
qsort(font->vmtx, font->vmtx_len, sizeof(pdf_vmtx), cmpv);
+ font->size += font->vmtx_cap * sizeof(pdf_vmtx);
}
pdf_hmtx
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c
index fdc48ff3..d798eb2e 100644
--- a/pdf/pdf_page.c
+++ b/pdf/pdf_page.c
@@ -275,10 +275,6 @@ pdf_load_page(pdf_xref *xref, int number)
if (number < 0 || number >= xref->page_len)
fz_throw(ctx, "cannot find page %d", number + 1);
- /* Ensure that we have a store for resource objects */
- if (!xref->store)
- xref->store = pdf_new_store(ctx);
-
pageobj = xref->page_objs[number];
pageref = xref->page_refs[number];
diff --git a/pdf/pdf_pattern.c b/pdf/pdf_pattern.c
index 194d9650..da890079 100644
--- a/pdf/pdf_pattern.c
+++ b/pdf/pdf_pattern.c
@@ -2,24 +2,54 @@
#include "mupdf.h"
pdf_pattern *
+pdf_keep_pattern(pdf_pattern *pat)
+{
+ return (pdf_pattern *)fz_keep_storable(&pat->storable);
+}
+
+void
+pdf_drop_pattern(fz_context *ctx, pdf_pattern *pat)
+{
+ fz_drop_storable(ctx, &pat->storable);
+}
+
+static void
+pdf_free_pattern_imp(fz_context *ctx, pdf_pattern *pat)
+{
+ if (pat->resources)
+ fz_drop_obj(pat->resources);
+ if (pat->contents)
+ fz_drop_buffer(ctx, pat->contents);
+ fz_free(ctx, pat);
+}
+
+static unsigned int
+pdf_pattern_size(pdf_pattern *pat)
+{
+ if (pat == NULL)
+ return 0;
+ return sizeof(*pat) + (pat->contents ? pat->contents->cap : 0);
+}
+
+pdf_pattern *
pdf_load_pattern(pdf_xref *xref, fz_obj *dict)
{
pdf_pattern *pat;
fz_obj *obj;
fz_context *ctx = xref->ctx;
- if ((pat = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_pattern, dict)))
+ if ((pat = fz_find_item(ctx, pdf_free_pattern_imp, dict)))
{
- return pdf_keep_pattern(pat);
+ return pat;
}
pat = fz_malloc(ctx, sizeof(pdf_pattern));
- pat->refs = 1;
+ FZ_INIT_STORABLE(pat, 1, pdf_free_pattern_imp);
pat->resources = NULL;
pat->contents = NULL;
/* Store pattern now, to avoid possible recursion if objects refer back to this one */
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_pattern, (pdf_store_drop_fn *)pdf_drop_pattern, dict, pat);
+ fz_store_item(ctx, dict, pat, pdf_pattern_size(pat));
pat->ismask = fz_to_int(fz_dict_gets(dict, "PaintType")) == 2;
pat->xstep = fz_to_real(fz_dict_gets(dict, "XStep"));
@@ -44,29 +74,9 @@ pdf_load_pattern(pdf_xref *xref, fz_obj *dict)
}
fz_catch(ctx)
{
- pdf_remove_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_pattern, dict);
+ fz_remove_item(ctx, pdf_free_pattern_imp, dict);
pdf_drop_pattern(ctx, pat);
fz_throw(ctx, "cannot load pattern stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
}
return pat;
}
-
-pdf_pattern *
-pdf_keep_pattern(pdf_pattern *pat)
-{
- pat->refs ++;
- return pat;
-}
-
-void
-pdf_drop_pattern(fz_context *ctx, pdf_pattern *pat)
-{
- if (pat && --pat->refs == 0)
- {
- if (pat->resources)
- fz_drop_obj(pat->resources);
- if (pat->contents)
- fz_drop_buffer(ctx, pat->contents);
- fz_free(ctx, pat);
- }
-}
diff --git a/pdf/pdf_shade.c b/pdf/pdf_shade.c
index e0a2804b..52e2f199 100644
--- a/pdf/pdf_shade.c
+++ b/pdf/pdf_shade.c
@@ -976,7 +976,7 @@ pdf_load_shading_dict(pdf_xref *xref, fz_obj *dict, fz_matrix transform)
fz_try(ctx)
{
shade = fz_malloc(ctx, sizeof(fz_shade));
- shade->refs = 1;
+ FZ_INIT_STORABLE(shade, 1, fz_free_shade_imp);
shade->type = FZ_MESH;
shade->use_background = 0;
shade->use_function = 0;
@@ -1077,6 +1077,14 @@ pdf_load_shading_dict(pdf_xref *xref, fz_obj *dict, fz_matrix transform)
return shade;
}
+static unsigned int
+fz_shade_size(fz_shade *s)
+{
+ if (s == NULL)
+ return 0;
+ return sizeof(*s) + s->mesh_cap * sizeof(*s->mesh) + s->colorspace->size;
+}
+
fz_shade *
pdf_load_shading(pdf_xref *xref, fz_obj *dict)
{
@@ -1085,9 +1093,9 @@ pdf_load_shading(pdf_xref *xref, fz_obj *dict)
fz_context *ctx = xref->ctx;
fz_shade *shade;
- if ((shade = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)fz_drop_shade, dict)))
+ if ((shade = fz_find_item(ctx, fz_free_shade_imp, dict)))
{
- return fz_keep_shade(shade);
+ return shade;
}
/* Type 2 pattern dictionary */
@@ -1123,7 +1131,7 @@ pdf_load_shading(pdf_xref *xref, fz_obj *dict)
/* RJW: "cannot load shading dictionary (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */
}
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)fz_keep_shade, (pdf_store_drop_fn *)fz_drop_shade, dict, shade);
+ fz_store_item(ctx, dict, shade, fz_shade_size(shade));
return shade;
}
diff --git a/pdf/pdf_store.c b/pdf/pdf_store.c
deleted file mode 100644
index 26a2ad9b..00000000
--- a/pdf/pdf_store.c
+++ /dev/null
@@ -1,224 +0,0 @@
-#include "fitz.h"
-#include "mupdf.h"
-
-typedef struct pdf_item_s pdf_item;
-
-struct pdf_item_s
-{
- pdf_store_drop_fn *drop_func;
- fz_obj *key;
- void *val;
- int age;
- pdf_item *next;
-};
-
-struct refkey
-{
- pdf_store_drop_fn *drop_func;
- int num;
- int gen;
-};
-
-struct pdf_store_s
-{
- fz_hash_table *hash; /* hash for num/gen keys */
- pdf_item *root; /* linked list for everything else */
-};
-
-pdf_store *
-pdf_new_store(fz_context *ctx)
-{
- pdf_store *store;
- store = fz_malloc(ctx, sizeof(pdf_store));
- store->hash = fz_new_hash_table(ctx, 4096, sizeof(struct refkey));
- store->root = NULL;
- return store;
-}
-
-void
-pdf_store_item(fz_context *ctx, pdf_store *store, pdf_store_keep_fn *keep_func, pdf_store_drop_fn *drop_func, fz_obj *key, void *val)
-{
- pdf_item *item;
-
- if (!store)
- return;
-
- item = fz_malloc(ctx, sizeof(pdf_item));
- item->drop_func = drop_func;
- item->key = fz_keep_obj(key);
- item->val = keep_func(val);
- item->age = 0;
- item->next = NULL;
-
- if (fz_is_indirect(key))
- {
- struct refkey refkey;
- refkey.drop_func = drop_func;
- refkey.num = fz_to_num(key);
- refkey.gen = fz_to_gen(key);
- fz_hash_insert(store->hash, &refkey, item);
- }
- else
- {
- item->next = store->root;
- store->root = item;
- }
-}
-
-void *
-pdf_find_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *drop_func, fz_obj *key)
-{
- struct refkey refkey;
- pdf_item *item;
-
- if (!store)
- return NULL;
-
- if (!key)
- return NULL;
-
- if (fz_is_indirect(key))
- {
- refkey.drop_func = drop_func;
- refkey.num = fz_to_num(key);
- refkey.gen = fz_to_gen(key);
- item = fz_hash_find(store->hash, &refkey);
- if (item)
- {
- item->age = 0;
- return item->val;
- }
- }
- else
- {
- for (item = store->root; item; item = item->next)
- {
- if (item->drop_func == drop_func && !fz_objcmp(item->key, key))
- {
- item->age = 0;
- return item->val;
- }
- }
- }
-
- return NULL;
-}
-
-void
-pdf_remove_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *drop_func, fz_obj *key)
-{
- struct refkey refkey;
- pdf_item *item, *prev, *next;
-
- if (fz_is_indirect(key))
- {
- refkey.drop_func = drop_func;
- refkey.num = fz_to_num(key);
- refkey.gen = fz_to_gen(key);
- item = fz_hash_find(store->hash, &refkey);
- if (item)
- {
- fz_hash_remove(store->hash, &refkey);
- item->drop_func(ctx, item->val);
- fz_drop_obj(item->key);
- fz_free(ctx, item);
- }
- }
- else
- {
- prev = NULL;
- for (item = store->root; item; item = next)
- {
- next = item->next;
- if (item->drop_func == drop_func && !fz_objcmp(item->key, key))
- {
- if (!prev)
- store->root = next;
- else
- prev->next = next;
- item->drop_func(ctx, item->val);
- fz_drop_obj(item->key);
- fz_free(ctx, item);
- }
- else
- prev = item;
- }
- }
-}
-
-void
-pdf_age_store(fz_context *ctx, pdf_store *store, int maxage)
-{
- struct refkey *refkey;
- pdf_item *item, *prev, *next;
- int i, n;
-
- n = fz_hash_len(store->hash);
- for (i = 0; i < n; i++)
- {
- refkey = fz_hash_get_key(store->hash, i);
- item = fz_hash_get_val(store->hash, i);
- if (item && ++item->age > maxage)
- {
- fz_hash_remove(store->hash, refkey);
- item->drop_func(ctx, item->val);
- fz_drop_obj(item->key);
- fz_free(ctx, item);
- i--; /* items with same hash may move into place */
- }
- }
-
- prev = NULL;
- for (item = store->root; item; item = next)
- {
- next = item->next;
- if (++item->age > maxage)
- {
- if (!prev)
- store->root = next;
- else
- prev->next = next;
- item->drop_func(ctx, item->val);
- fz_drop_obj(item->key);
- fz_free(ctx, item);
- }
- else
- prev = item;
- }
-}
-
-void
-pdf_free_store(fz_context *ctx, pdf_store *store)
-{
- pdf_age_store(ctx, store, 0);
- fz_free_hash(store->hash);
- fz_free(ctx, store);
-}
-
-void
-pdf_debug_store(fz_context *ctx, pdf_store *store)
-{
- pdf_item *item;
- pdf_item *next;
- struct refkey *refkey;
- int i, n;
-
- printf("-- resource store contents --\n");
-
- n = fz_hash_len(store->hash);
- for (i = 0; i < n; i++)
- {
- refkey = fz_hash_get_key(store->hash, i);
- item = fz_hash_get_val(store->hash, i);
- if (item)
- printf("store[%d] (%d %d R) = %p\n", i, refkey->num, refkey->gen, item->val);
- }
-
- for (item = store->root; item; item = next)
- {
- next = item->next;
- printf("store[*] ");
- fz_debug_obj(item->key);
- printf(" = %p\n", item->val);
- }
-}
diff --git a/pdf/pdf_type3.c b/pdf/pdf_type3.c
index c129350a..c63a2642 100644
--- a/pdf/pdf_type3.c
+++ b/pdf/pdf_type3.c
@@ -40,6 +40,7 @@ pdf_load_type3_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
bbox = pdf_to_rect(ctx, obj);
fontdesc->font = fz_new_type3_font(ctx, buf, matrix);
+ fontdesc->size += sizeof(fz_font) + 256 * (sizeof(fz_buffer*) + sizeof(float));
fz_set_font_bbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
@@ -84,6 +85,7 @@ pdf_load_type3_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
}
fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
+ fontdesc->size += pdf_cmap_size(fontdesc->encoding);
pdf_load_to_unicode(fontdesc, xref, estrings, NULL, fz_dict_gets(dict, "ToUnicode"));
@@ -139,6 +141,7 @@ pdf_load_type3_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
if (pdf_is_stream(xref, fz_to_num(obj), fz_to_gen(obj)))
{
fontdesc->font->t3procs[i] = pdf_load_stream(xref, fz_to_num(obj), fz_to_gen(obj));
+ fontdesc->size += fontdesc->font->t3procs[i]->cap;
}
}
}
diff --git a/pdf/pdf_unicode.c b/pdf/pdf_unicode.c
index 7968036a..95e7fa00 100644
--- a/pdf/pdf_unicode.c
+++ b/pdf/pdf_unicode.c
@@ -37,6 +37,7 @@ pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref,
pdf_sort_cmap(ctx, font->to_unicode);
pdf_drop_cmap(ctx, cmap);
+ font->size += pdf_cmap_size(font->to_unicode);
}
else if (collection)
@@ -60,6 +61,7 @@ pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref,
font->cid_to_ucs_len = 256;
font->cid_to_ucs = fz_malloc_array(ctx, 256, sizeof(unsigned short));
+ font->size += 256 * sizeof(unsigned short);
for (i = 0; i < 256; i++)
{
diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c
index b4c03b8b..913ded37 100644
--- a/pdf/pdf_xobject.c
+++ b/pdf/pdf_xobject.c
@@ -2,25 +2,57 @@
#include "mupdf.h"
pdf_xobject *
+pdf_keep_xobject(pdf_xobject *xobj)
+{
+ return (pdf_xobject *)fz_keep_storable(&xobj->storable);
+}
+
+void
+pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj)
+{
+ fz_drop_storable(ctx, &xobj->storable);
+}
+
+static void
+pdf_free_xobject_imp(fz_context *ctx, pdf_xobject *xobj)
+{
+ if (xobj->colorspace)
+ fz_drop_colorspace(ctx, xobj->colorspace);
+ if (xobj->resources)
+ fz_drop_obj(xobj->resources);
+ if (xobj->contents)
+ fz_drop_buffer(ctx, xobj->contents);
+ fz_free(ctx, xobj);
+}
+
+static unsigned int
+pdf_xobject_size(pdf_xobject *xobj)
+{
+ if (xobj == NULL)
+ return 0;
+ return sizeof(*xobj) + (xobj->colorspace ? xobj->colorspace->size : 0) + (xobj->contents ? xobj->contents->len : 0);
+}
+
+pdf_xobject *
pdf_load_xobject(pdf_xref *xref, fz_obj *dict)
{
pdf_xobject *form;
fz_obj *obj;
fz_context *ctx = xref->ctx;
- if ((form = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_xobject, dict)))
+ if ((form = fz_find_item(ctx, pdf_free_xobject_imp, dict)))
{
- return pdf_keep_xobject(form);
+ return form;
}
form = fz_malloc(ctx, sizeof(pdf_xobject));
- form->refs = 1;
+ FZ_INIT_STORABLE(form, 1, pdf_free_xobject_imp);
form->resources = NULL;
form->contents = NULL;
form->colorspace = NULL;
/* Store item immediately, to avoid possible recursion if objects refer back to this one */
- pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_xobject, (pdf_store_drop_fn *)pdf_drop_xobject, dict, form);
+ fz_store_item(ctx, dict, form, pdf_xobject_size(form));
obj = fz_dict_gets(dict, "BBox");
form->bbox = pdf_to_rect(ctx, obj);
@@ -66,32 +98,10 @@ pdf_load_xobject(pdf_xref *xref, fz_obj *dict)
}
fz_catch(ctx)
{
- pdf_remove_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_xobject, dict);
+ fz_remove_item(ctx, pdf_free_xobject_imp, dict);
pdf_drop_xobject(ctx, form);
fz_throw(ctx, "cannot load xobject content stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
}
return form;
}
-
-pdf_xobject *
-pdf_keep_xobject(pdf_xobject *xobj)
-{
- xobj->refs ++;
- return xobj;
-}
-
-void
-pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj)
-{
- if (xobj && --xobj->refs == 0)
- {
- if (xobj->colorspace)
- fz_drop_colorspace(ctx, xobj->colorspace);
- if (xobj->resources)
- fz_drop_obj(xobj->resources);
- if (xobj->contents)
- fz_drop_buffer(ctx, xobj->contents);
- fz_free(ctx, xobj);
- }
-}
diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c
index f79c6f9a..6b05e969 100644
--- a/pdf/pdf_xref.c
+++ b/pdf/pdf_xref.c
@@ -783,9 +783,6 @@ pdf_free_xref(pdf_xref *xref)
return;
ctx = xref->ctx;
- if (xref->store)
- pdf_free_store(ctx, xref->store);
-
if (xref->table)
{
for (i = 0; i < xref->len; i++)