summaryrefslogtreecommitdiff
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
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.
-rw-r--r--apps/pdfapp.c6
-rw-r--r--apps/pdfclean.c2
-rw-r--r--apps/pdfdraw.c4
-rw-r--r--apps/pdfextract.c2
-rw-r--r--apps/pdfshow.c2
-rw-r--r--apps/win_main.c2
-rw-r--r--apps/xpsdraw.c2
-rw-r--r--fitz/base_context.c6
-rw-r--r--fitz/fitz.h51
-rw-r--r--fitz/res_colorspace.c35
-rw-r--r--fitz/res_pixmap.c58
-rw-r--r--fitz/res_shade.c22
-rw-r--r--fitz/res_store.c364
-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
-rw-r--r--scripts/cmapdump.c21
-rw-r--r--win32/libmupdf.vcproj8
-rw-r--r--xps/xps_gradient.c4
32 files changed, 727 insertions, 462 deletions
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index 9893af39..c1e026fe 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -259,10 +259,6 @@ void pdfapp_close(pdfapp_t *app)
if (app->xref)
{
- if (app->xref->store)
- pdf_free_store(app->ctx, app->xref->store);
- app->xref->store = NULL;
-
pdf_free_xref(app->xref);
app->xref = NULL;
}
@@ -347,7 +343,7 @@ static void pdfapp_loadpage_pdf(pdfapp_t *app)
pdf_free_page(app->ctx, page);
- pdf_age_store(app->ctx, app->xref->store, 3);
+ fz_age_store(app->ctx, 3);
}
static void pdfapp_loadpage_xps(pdfapp_t *app)
diff --git a/apps/pdfclean.c b/apps/pdfclean.c
index e13ad0f6..e8c27359 100644
--- a/apps/pdfclean.c
+++ b/apps/pdfclean.c
@@ -767,7 +767,7 @@ int main(int argc, char **argv)
if (argc - fz_optind > 0)
subset = 1;
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c
index 861d2b3f..af1d5ad7 100644
--- a/apps/pdfdraw.c
+++ b/apps/pdfdraw.c
@@ -263,7 +263,7 @@ static void drawpage(pdf_xref *xref, int pagenum)
if (showmd5 || showtime)
printf("\n");
- pdf_age_store(ctx, xref->store, 3);
+ fz_age_store(ctx, 3);
fz_flush_warnings(ctx);
}
@@ -362,7 +362,7 @@ int main(int argc, char **argv)
if (accelerate)
fz_accelerate();
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
diff --git a/apps/pdfextract.c b/apps/pdfextract.c
index c32a25c5..590bf13f 100644
--- a/apps/pdfextract.c
+++ b/apps/pdfextract.c
@@ -178,7 +178,7 @@ int main(int argc, char **argv)
infile = argv[fz_optind++];
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
diff --git a/apps/pdfshow.c b/apps/pdfshow.c
index c437f262..0c3feaf2 100644
--- a/apps/pdfshow.c
+++ b/apps/pdfshow.c
@@ -189,7 +189,7 @@ int main(int argc, char **argv)
filename = argv[fz_optind++];
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
diff --git a/apps/win_main.c b/apps/win_main.c
index eb0e6085..0af83aec 100644
--- a/apps/win_main.c
+++ b/apps/win_main.c
@@ -831,7 +831,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShow
fz_accelerate();
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
diff --git a/apps/xpsdraw.c b/apps/xpsdraw.c
index a7223574..f583057e 100644
--- a/apps/xpsdraw.c
+++ b/apps/xpsdraw.c
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
if (accelerate)
fz_accelerate();
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
diff --git a/fitz/base_context.c b/fitz/base_context.c
index 3d9df6aa..e722aa1d 100644
--- a/fitz/base_context.c
+++ b/fitz/base_context.c
@@ -15,6 +15,7 @@ fz_free_context(fz_context *ctx)
return;
/* Other finalisation calls go here (in reverse order) */
+ fz_free_store_context(ctx);
fz_free_aa_context(ctx);
fz_free_font_context(ctx);
@@ -30,7 +31,7 @@ fz_free_context(fz_context *ctx)
}
fz_context *
-fz_new_context(fz_alloc_context *alloc)
+fz_new_context(fz_alloc_context *alloc, unsigned int max_store)
{
fz_context *ctx;
@@ -57,6 +58,7 @@ fz_new_context(fz_alloc_context *alloc)
{
fz_new_font_context(ctx);
fz_new_aa_context(ctx);
+ fz_new_store_context(ctx, max_store);
}
fz_catch(ctx)
{
@@ -74,5 +76,5 @@ cleanup:
fz_context *
fz_clone_context(fz_context *ctx)
{
- return fz_new_context(ctx->alloc);
+ return fz_new_context(ctx->alloc, FZ_STORE_UNLIMITED);
}
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 8d523e3f..ebbd176c 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -100,6 +100,7 @@ typedef struct fz_error_context_s fz_error_context;
typedef struct fz_warn_context_s fz_warn_context;
typedef struct fz_font_context_s fz_font_context;
typedef struct fz_aa_context_s fz_aa_context;
+typedef struct fz_store_s fz_store;
typedef struct fz_context_s fz_context;
struct fz_alloc_context_s
@@ -156,9 +157,10 @@ struct fz_context_s
fz_warn_context *warn;
fz_font_context *font;
fz_aa_context *aa;
+ fz_store *store;
};
-fz_context *fz_new_context(fz_alloc_context *alloc);
+fz_context *fz_new_context(fz_alloc_context *alloc, unsigned int max_store);
fz_context *fz_clone_context(fz_context *ctx);
void fz_free_context(fz_context *ctx);
@@ -490,6 +492,42 @@ void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size);
void fz_grow_buffer(fz_context *ctx, fz_buffer *buf);
/*
+ * Resource store
+ */
+
+typedef struct fz_storable_s fz_storable;
+
+typedef struct fz_item_s fz_item;
+
+typedef void (fz_store_free_fn)(fz_context *, void *);
+
+struct fz_storable_s {
+ int refs;
+ fz_store_free_fn *free;
+};
+
+#define FZ_INIT_STORABLE(S_,RC,FREE) \
+ do { fz_storable *S = &(S_)->storable; S->refs = (RC); \
+ S->free = (FREE); \
+ } while (0)
+
+enum {
+ FZ_STORE_UNLIMITED = 0
+};
+
+void fz_new_store_context(fz_context *ctx, unsigned int max);
+void fz_free_store_context(fz_context *ctx);
+void fz_debug_store(fz_context *ctx);
+
+void *fz_keep_storable(fz_storable *);
+void fz_drop_storable(fz_context *, fz_storable *);
+
+void fz_store_item(fz_context *ctx, fz_obj *key, void *val, unsigned int itemsize);
+void *fz_find_item(fz_context *ctx, fz_store_free_fn *freefn, fz_obj *key);
+void fz_remove_item(fz_context *ctx, fz_store_free_fn *freefn, fz_obj *key);
+void fz_age_store(fz_context *ctx, int maxage);
+
+/*
* Buffered reader.
* Only the data between rp and wp is valid data.
*/
@@ -648,7 +686,7 @@ typedef struct fz_colorspace_s fz_colorspace;
struct fz_pixmap_s
{
- int refs;
+ fz_storable storable;
int x, y, w, h, n;
fz_pixmap *mask; /* explicit soft/image mask */
int interpolate;
@@ -667,6 +705,7 @@ fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *, fz
fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h);
fz_pixmap *fz_keep_pixmap(fz_pixmap *pix);
void fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix);
+void fz_free_pixmap_imp(fz_context *ctx, void *pix);
void fz_clear_pixmap(fz_pixmap *pix);
void fz_clear_pixmap_with_color(fz_pixmap *pix, int value);
void fz_clear_pixmap_rect_with_color(fz_pixmap *pix, int value, fz_bbox r);
@@ -677,6 +716,7 @@ fz_pixmap *fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity);
fz_bbox fz_bound_pixmap(fz_pixmap *pix);
void fz_invert_pixmap(fz_pixmap *pix);
void fz_gamma_pixmap(fz_pixmap *pix, float gamma);
+unsigned int fz_pixmap_size(fz_pixmap *pix);
fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h);
@@ -740,7 +780,8 @@ extern fz_colorspace *fz_device_cmyk;
struct fz_colorspace_s
{
- int refs;
+ fz_storable storable;
+ unsigned int size;
char name[16];
int n;
void (*to_rgb)(fz_context *ctx, fz_colorspace *, float *src, float *rgb);
@@ -752,6 +793,7 @@ struct fz_colorspace_s
fz_colorspace *fz_new_colorspace(fz_context *ctx, char *name, int n);
fz_colorspace *fz_keep_colorspace(fz_colorspace *colorspace);
void fz_drop_colorspace(fz_context *ctx, fz_colorspace *colorspace);
+void fz_free_colorspace_imp(fz_context *ctx, void *colorspace);
void fz_convert_color(fz_context *ctx, fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv);
void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst);
@@ -928,7 +970,7 @@ typedef struct fz_shade_s fz_shade;
struct fz_shade_s
{
- int refs;
+ fz_storable storable;
fz_rect bbox; /* can be fz_infinite_rect */
fz_colorspace *colorspace;
@@ -950,6 +992,7 @@ struct fz_shade_s
fz_shade *fz_keep_shade(fz_shade *shade);
void fz_drop_shade(fz_context *ctx, fz_shade *shade);
+void fz_free_shade_imp(fz_context *ctx, void *shade);
void fz_debug_shade(fz_shade *shade);
fz_rect fz_bound_shade(fz_shade *shade, fz_matrix ctm);
diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c
index 85556b62..8f145658 100644
--- a/fitz/res_colorspace.c
+++ b/fitz/res_colorspace.c
@@ -2,11 +2,22 @@
#define SLOWCMYK
+void
+fz_free_colorspace_imp(fz_context *ctx, void *cs_)
+{
+ fz_colorspace *cs = (fz_colorspace *)cs_;
+
+ if (cs->free_data && cs->data)
+ cs->free_data(ctx, cs);
+ fz_free(ctx, cs);
+}
+
fz_colorspace *
fz_new_colorspace(fz_context *ctx, char *name, int n)
{
fz_colorspace *cs = fz_malloc(ctx, sizeof(fz_colorspace));
- cs->refs = 1;
+ FZ_INIT_STORABLE(cs, 1, fz_free_colorspace_imp);
+ cs->size = sizeof(fz_colorspace);
fz_strlcpy(cs->name, name, sizeof cs->name);
cs->n = n;
cs->to_rgb = NULL;
@@ -19,23 +30,13 @@ fz_new_colorspace(fz_context *ctx, char *name, int n)
fz_colorspace *
fz_keep_colorspace(fz_colorspace *cs)
{
- if (cs->refs < 0)
- return cs;
- cs->refs ++;
- return cs;
+ return (fz_colorspace *)fz_keep_storable(&cs->storable);
}
void
fz_drop_colorspace(fz_context *ctx, fz_colorspace *cs)
{
- if (cs && cs->refs < 0)
- return;
- if (cs && --cs->refs == 0)
- {
- if (cs->free_data && cs->data)
- cs->free_data(ctx, cs);
- fz_free(ctx, cs);
- }
+ fz_drop_storable(ctx, &cs->storable);
}
/* Device colorspace definitions */
@@ -152,10 +153,10 @@ static void rgb_to_cmyk(fz_context *ctx, fz_colorspace *cs, float *rgb, float *c
cmyk[3] = k;
}
-static fz_colorspace k_device_gray = { -1, "DeviceGray", 1, gray_to_rgb, rgb_to_gray };
-static fz_colorspace k_device_rgb = { -1, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb };
-static fz_colorspace k_device_bgr = { -1, "DeviceRGB", 3, bgr_to_rgb, rgb_to_bgr };
-static fz_colorspace k_device_cmyk = { -1, "DeviceCMYK", 4, cmyk_to_rgb, rgb_to_cmyk };
+static fz_colorspace k_device_gray = { {-1, fz_free_colorspace_imp}, 0, "DeviceGray", 1, gray_to_rgb, rgb_to_gray };
+static fz_colorspace k_device_rgb = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb };
+static fz_colorspace k_device_bgr = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, bgr_to_rgb, rgb_to_bgr };
+static fz_colorspace k_device_cmyk = { {-1, fz_free_colorspace_imp}, 0, "DeviceCMYK", 4, cmyk_to_rgb, rgb_to_cmyk };
fz_colorspace *fz_device_gray = &k_device_gray;
fz_colorspace *fz_device_rgb = &k_device_rgb;
diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c
index 1dfc8ad0..c8ae7540 100644
--- a/fitz/res_pixmap.c
+++ b/fitz/res_pixmap.c
@@ -4,12 +4,37 @@ static int fz_memory_limit = 256 << 20;
static int fz_memory_used = 0;
fz_pixmap *
+fz_keep_pixmap(fz_pixmap *pix)
+{
+ return (fz_pixmap *)fz_keep_storable(&pix->storable);
+}
+
+void
+fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix)
+{
+ fz_drop_storable(ctx, &pix->storable);
+}
+
+void
+fz_free_pixmap_imp(fz_context *ctx, fz_pixmap *pix)
+{
+ fz_memory_used -= pix->w * pix->h * pix->n;
+ if (pix->mask)
+ fz_drop_pixmap(ctx, pix->mask);
+ if (pix->colorspace)
+ fz_drop_colorspace(ctx, pix->colorspace);
+ if (pix->free_samples)
+ fz_free(ctx, pix->samples);
+ fz_free(ctx, pix);
+}
+
+fz_pixmap *
fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples)
{
fz_pixmap *pix;
pix = fz_malloc(ctx, sizeof(fz_pixmap));
- pix->refs = 1;
+ FZ_INIT_STORABLE(pix, 1, fz_free_pixmap_imp);
pix->x = 0;
pix->y = 0;
pix->w = w;
@@ -82,29 +107,6 @@ fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_
return pixmap;
}
-fz_pixmap *
-fz_keep_pixmap(fz_pixmap *pix)
-{
- pix->refs++;
- return pix;
-}
-
-void
-fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- if (pix && --pix->refs == 0)
- {
- fz_memory_used -= pix->w * pix->h * pix->n;
- if (pix->mask)
- fz_drop_pixmap(ctx, pix->mask);
- if (pix->colorspace)
- fz_drop_colorspace(ctx, pix->colorspace);
- if (pix->free_samples)
- fz_free(ctx, pix->samples);
- fz_free(ctx, pix);
- }
-}
-
fz_bbox
fz_bound_pixmap(fz_pixmap *pix)
{
@@ -533,3 +535,11 @@ fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha)
fz_free(ctx, udata);
fz_free(ctx, cdata);
}
+
+unsigned int
+fz_pixmap_size(fz_pixmap * pix)
+{
+ if (pix == NULL)
+ return 0;
+ return sizeof(*pix) + pix->n * pix->x * pix->y;
+}
diff --git a/fitz/res_shade.c b/fitz/res_shade.c
index b7617161..c2a8c858 100644
--- a/fitz/res_shade.c
+++ b/fitz/res_shade.c
@@ -3,20 +3,24 @@
fz_shade *
fz_keep_shade(fz_shade *shade)
{
- shade->refs ++;
- return shade;
+ return (fz_shade *)fz_keep_storable(&shade->storable);
+}
+
+void
+fz_free_shade_imp(fz_context *ctx, void *shade_)
+{
+ fz_shade *shade = (fz_shade *)shade_;
+
+ if (shade->colorspace)
+ fz_drop_colorspace(ctx, shade->colorspace);
+ fz_free(ctx, shade->mesh);
+ fz_free(ctx, shade);
}
void
fz_drop_shade(fz_context *ctx, fz_shade *shade)
{
- if (shade && --shade->refs == 0)
- {
- if (shade->colorspace)
- fz_drop_colorspace(ctx, shade->colorspace);
- fz_free(ctx, shade->mesh);
- fz_free(ctx, shade);
- }
+ fz_drop_storable(ctx, &shade->storable);
}
fz_rect
diff --git a/fitz/res_store.c b/fitz/res_store.c
new file mode 100644
index 00000000..08885c30
--- /dev/null
+++ b/fitz/res_store.c
@@ -0,0 +1,364 @@
+#include "fitz.h"
+#include "mupdf.h"
+
+struct fz_item_s
+{
+ fz_obj *key;
+ fz_storable *val;
+ unsigned int size;
+ fz_item *next;
+ fz_item *prev;
+ fz_store *store;
+ int age;
+};
+
+struct refkey
+{
+ fz_store_free_fn *free;
+ int num;
+ int gen;
+};
+
+struct fz_store_s
+{
+ /* Every item in the store is kept in a doubly linked list, ordered
+ * by usage (so LRU entries are at the end). */
+ fz_item *head;
+ fz_item *tail;
+
+ /* We have a hash table that allows to quickly find a subset of the
+ * entries (those whose keys are indirect objects). */
+ fz_hash_table *hash;
+
+ /* We keep track of the size of the store, and keep it below max. */
+ unsigned int max;
+ unsigned int size;
+};
+
+void
+fz_new_store_context(fz_context *ctx, unsigned int max)
+{
+ fz_store *store;
+ store = fz_malloc(ctx, sizeof(fz_store));
+ store->hash = fz_new_hash_table(ctx, 4096, sizeof(struct refkey));
+ store->head = NULL;
+ store->tail = NULL;
+ store->size = 0;
+ store->max = max;
+ ctx->store = store;
+}
+
+void *
+fz_keep_storable(fz_storable *s)
+{
+ if (s == NULL)
+ return NULL;
+ /* LOCK */
+ if (s->refs > 0)
+ s->refs++;
+ /* UNLOCK */
+ return s;
+}
+
+void
+fz_drop_storable(fz_context *ctx, fz_storable *s)
+{
+ if (s == NULL)
+ return;
+ /* LOCK */
+ if (s->refs < 0)
+ {
+ /* It's a static object. Dropping does nothing. */
+ }
+ else if (--s->refs == 0)
+ {
+ /* If we are dropping the last reference to an object, then
+ * it cannot possibly be in the store (as the store always
+ * keeps a ref to everything in it, and doesn't drop via
+ * this method. So we can simply drop the storable object
+ * itself without any operations on the fz_store. */
+ s->free(ctx, s);
+ }
+ /* UNLOCK */
+}
+
+static void
+evict(fz_context *ctx, fz_store *store, fz_item *item)
+{
+ store->size -= item->size;
+ /* Unlink from the linked list */
+ if (item->next)
+ item->next->prev = item->prev;
+ else
+ store->tail = item->prev;
+ if (item->prev)
+ item->prev->next = item->next;
+ else
+ store->head = item->next;
+ /* Remove from the hash table */
+ if (fz_is_indirect(item->key))
+ {
+ struct refkey refkey;
+ refkey.free = item->val->free;
+ refkey.num = fz_to_num(item->key);
+ refkey.gen = fz_to_gen(item->key);
+ fz_hash_remove(store->hash, &refkey);
+ }
+ /* Drop the value, key and item */
+ item->val->free(ctx, item->val);
+ fz_drop_obj(item->key);
+ fz_free(ctx, item);
+}
+
+static int
+ensure_space(fz_context *ctx, unsigned int tofree)
+{
+ fz_item *item, *prev;
+ unsigned int count;
+ fz_store *store = ctx->store;
+
+ /* First check that we *can* free tofree; if not, we'd rather not
+ * cache this. */
+ count = 0;
+ for (item = store->tail; item; item = item->prev)
+ {
+ if (item->val->refs == 1)
+ {
+ count += item->size;
+ if (count >= tofree)
+ break;
+ }
+ }
+
+ /* If we ran out of items to search, then we can never free enough */
+ if (item == NULL)
+ return 1;
+
+ /* Actually free the items */
+ count = 0;
+ for (item = store->tail; item; item = prev)
+ {
+ prev = item->prev;
+ if (item->val->refs == 1)
+ {
+ /* Free this item */
+ count += item->size;
+ evict(ctx, store, item);
+
+ if (count >= tofree)
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void
+fz_store_item(fz_context *ctx, fz_obj *key, void *val_, unsigned int itemsize)
+{
+ fz_item *item;
+ unsigned int size;
+ fz_storable *val = (fz_storable *)val_;
+ fz_store *store = ctx->store;
+
+ if (!store)
+ return;
+
+ item = fz_malloc(ctx, sizeof(*item));
+ /* LOCK */
+ size = store->size + itemsize;
+ if (store->max != FZ_STORE_UNLIMITED && size > store->max && ensure_space(ctx, size - store->max))
+ {
+ fz_free(ctx, item);
+ /* UNLOCK */
+ return;
+ }
+ store->size += itemsize;
+
+ item->key = fz_keep_obj(key);
+ item->val = val;
+ item->size = itemsize;
+ item->next = NULL;
+ if (val->refs > 0)
+ val->refs++;
+
+ /* If we can index it fast, put it into the hash table */
+ if (fz_is_indirect(key))
+ {
+ struct refkey refkey;
+ refkey.free = val->free;
+ refkey.num = fz_to_num(key);
+ refkey.gen = fz_to_gen(key);
+ fz_hash_insert(store->hash, &refkey, item);
+ }
+ /* Regardless of whether it's indexed, it goes into the linked list */
+ item->next = store->head;
+ if (item->next)
+ item->next->prev = item;
+ else
+ store->tail = item;
+ store->head = item;
+ item->prev = NULL;
+ /* UNLOCK */
+}
+
+void *
+fz_find_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key)
+{
+ struct refkey refkey;
+ fz_item *item;
+ fz_store *store = ctx->store;
+
+ if (!store)
+ return NULL;
+
+ if (!key)
+ return NULL;
+
+ /* LOCK */
+ if (fz_is_indirect(key))
+ {
+ /* We can find objects keyed on indirected objects quickly */
+ refkey.free = free;
+ refkey.num = fz_to_num(key);
+ refkey.gen = fz_to_gen(key);
+ item = fz_hash_find(store->hash, &refkey);
+ }
+ else
+ {
+ /* Others we have to hunt for slowly */
+ for (item = store->head; item; item = item->next)
+ {
+ if (item->val->free == free && !fz_objcmp(item->key, key))
+ break;
+ }
+ }
+ if (item)
+ {
+ /* LRU: Move the block to the front */
+ /* Unlink from present position */
+ if (item->next)
+ item->next->prev = item->prev;
+ else
+ store->tail = item->prev;
+ if (item->prev)
+ item->prev->next = item->next;
+ else
+ store->head = item->next;
+ /* Insert at head */
+ item->next = store->head;
+ if (item->next)
+ item->next->prev = item;
+ else
+ store->tail = item;
+ item->prev = NULL;
+ store->head = item;
+ /* And bump the refcount before returning */
+ if (item->val->refs > 0)
+ item->val->refs++;
+ /* UNLOCK */
+ return (void *)item->val;
+ }
+ /* UNLOCK */
+
+ return NULL;
+}
+
+void
+fz_remove_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key)
+{
+ struct refkey refkey;
+ fz_item *item;
+ fz_store *store = ctx->store;
+
+ /* LOCK */
+ if (fz_is_indirect(key))
+ {
+ /* We can find objects keyed on indirect objects quickly */
+ refkey.free = free;
+ 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);
+ }
+ else
+ {
+ /* Others we have to hunt for slowly */
+ for (item = store->head; item; item = item->next)
+ if (item->val->free == free && !fz_objcmp(item->key, key))
+ break;
+ }
+ if (item)
+ {
+ if (item->next)
+ item->next->prev = item->prev;
+ else
+ store->tail = item->prev;
+ if (item->prev)
+ item->prev->next = item->next;
+ else
+ store->head = item->next;
+ if (item->val->refs > 0 && --item->val->refs == 0)
+ item->val->free(ctx, item->val);
+ fz_drop_obj(item->key);
+ fz_free(ctx, item);
+ }
+ /* UNLOCK */
+}
+
+void
+fz_age_store(fz_context *ctx, int maxage)
+{
+ fz_item *item, *next;
+ fz_store *store = ctx->store;
+
+ if (store == NULL)
+ return;
+
+ /* LOCK */
+ /* Run through all the items in the store */
+ for (item = store->head; item; item = next)
+ {
+ next = item->next;
+ /* If we've only got 1 reference, then we must be the only
+ * holders. Age the item. If it's older than the maximum,
+ * bin it. */
+ if (item->val->refs == 1 && ++item->age > maxage)
+ evict(ctx, store, item);
+ }
+ /* UNLOCK */
+}
+
+void
+fz_free_store_context(fz_context *ctx)
+{
+ if (ctx == NULL || ctx->store == NULL)
+ return;
+ fz_age_store(ctx, 0);
+ fz_free_hash(ctx->store->hash);
+ fz_free(ctx, ctx->store);
+ ctx->store = NULL;
+}
+
+void
+fz_debug_store(fz_context *ctx)
+{
+ fz_item *item;
+ fz_store *store = ctx->store;
+
+ printf("-- resource store contents --\n");
+
+ /* LOCK */
+ for (item = store->head; item; item = item->next)
+ {
+ printf("store[*][claim=%d] ", item->val->refs);
+ if (fz_is_indirect(item->key))
+ {
+ printf("(%d %d R) ", fz_to_num(item->key), fz_to_gen(item->key));
+ } else
+ fz_debug_obj(item->key);
+ printf(" = %p\n", item->val);
+ }
+ /* UNLOCK */
+}
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++)
diff --git a/scripts/cmapdump.c b/scripts/cmapdump.c
index 286f2abe..c8ae8134 100644
--- a/scripts/cmapdump.c
+++ b/scripts/cmapdump.c
@@ -49,7 +49,7 @@ main(int argc, char **argv)
return 1;
}
- ctx = fz_new_context(&fz_alloc_default);
+ ctx = fz_new_context(&fz_alloc_default, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
@@ -122,7 +122,7 @@ main(int argc, char **argv)
}
fprintf(fo, "static pdf_cmap cmap_%s = {\n", name);
- fprintf(fo, "\t-1, ");
+ fprintf(fo, "\t{-1, pdf_free_cmap_imp}, ");
fprintf(fo, "\"%s\", ", cmap->cmap_name);
fprintf(fo, "\"%s\", 0, ", cmap->usecmap_name);
fprintf(fo, "%d, ", cmap->wmode);
@@ -175,3 +175,20 @@ void fz_new_aa_context(fz_context *ctx)
void fz_free_aa_context(fz_context *ctx)
{
}
+
+void *fz_keep_storable(fz_storable *s)
+{
+ return s;
+}
+
+void fz_drop_storable(fz_context *ctx, fz_storable *s)
+{
+}
+
+void fz_new_store_context(fz_context *ctx, unsigned int max)
+{
+}
+
+void fz_free_store_context(fz_context *ctx)
+{
+}
diff --git a/win32/libmupdf.vcproj b/win32/libmupdf.vcproj
index 52977dca..663f0268 100644
--- a/win32/libmupdf.vcproj
+++ b/win32/libmupdf.vcproj
@@ -311,10 +311,6 @@
>
</File>
<File
- RelativePath="..\pdf\pdf_store.c"
- >
- </File>
- <File
RelativePath="..\pdf\pdf_stream.c"
>
</File>
@@ -487,6 +483,10 @@
>
</File>
<File
+ RelativePath="..\fitz\res_store.c"
+ >
+ </File>
+ <File
RelativePath="..\fitz\res_text.c"
>
</File>
diff --git a/xps/xps_gradient.c b/xps/xps_gradient.c
index b13d14ef..e5acc8a0 100644
--- a/xps/xps_gradient.c
+++ b/xps/xps_gradient.c
@@ -213,7 +213,7 @@ xps_draw_one_radial_gradient(xps_document *doc, fz_matrix ctm,
/* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */
shade = fz_malloc(doc->ctx, sizeof(fz_shade));
- shade->refs = 1;
+ FZ_INIT_STORABLE(shade, 1, fz_free_shade_imp);
shade->colorspace = fz_device_rgb;
shade->bbox = fz_infinite_rect;
shade->matrix = fz_identity;
@@ -254,7 +254,7 @@ xps_draw_one_linear_gradient(xps_document *doc, fz_matrix ctm,
/* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */
shade = fz_malloc(doc->ctx, sizeof(fz_shade));
- shade->refs = 1;
+ FZ_INIT_STORABLE(shade, 1, fz_free_shade_imp);
shade->colorspace = fz_device_rgb;
shade->bbox = fz_infinite_rect;
shade->matrix = fz_identity;