diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/fitz/image.c | 56 | ||||
-rw-r--r-- | source/fitz/store.c | 122 | ||||
-rw-r--r-- | source/gprf/gprf-doc.c | 2 |
3 files changed, 164 insertions, 16 deletions
diff --git a/source/fitz/image.c b/source/fitz/image.c index e6772783..247cb088 100644 --- a/source/fitz/image.c +++ b/source/fitz/image.c @@ -18,18 +18,6 @@ struct fz_pixmap_image_s fz_pixmap *tile; }; -fz_image * -fz_keep_image(fz_context *ctx, fz_image *image) -{ - return fz_keep_storable(ctx, &image->storable); -} - -void -fz_drop_image(fz_context *ctx, fz_image *image) -{ - fz_drop_storable(ctx, &image->storable); -} - typedef struct fz_image_key_s fz_image_key; struct fz_image_key_s { @@ -39,6 +27,24 @@ struct fz_image_key_s { fz_irect rect; }; +fz_image * +fz_keep_image(fz_context *ctx, fz_image *image) +{ + return fz_keep_key_storable(ctx, &image->key_storable); +} + +fz_image * +fz_keep_image_store_key(fz_context *ctx, fz_image *image) +{ + return fz_keep_key_storable_key(ctx, &image->key_storable); +} + +void +fz_drop_image_store_key(fz_context *ctx, fz_image *image) +{ + fz_drop_key_storable_key(ctx, &image->key_storable); +} + static int fz_make_hash_image_key(fz_context *ctx, fz_store_hash *hash, void *key_) { @@ -62,7 +68,7 @@ fz_drop_image_key(fz_context *ctx, void *key_) fz_image_key *key = (fz_image_key *)key_; if (fz_drop_imp(ctx, key, &key->refs)) { - fz_drop_image(ctx, key->image); + fz_drop_image_store_key(ctx, key->image); fz_free(ctx, key); } } @@ -91,6 +97,26 @@ static fz_store_type fz_image_store_type = fz_print_image }; +static int +drop_matching_images(fz_context *ctx, void *image_, void *key_) +{ + fz_image_key *key = (fz_image_key *)key_; + fz_image *image = (fz_image *)image_; + + return key->image == image; +} + +void +fz_drop_image(fz_context *ctx, fz_image *image) +{ + if (fz_drop_key_storable(ctx, &image->key_storable)) + { + /* All the image refs left are references from keys in the store. */ + /* We can never hope to match these keys again, so drop the objects. */ + fz_filter_store(ctx, drop_matching_images, image, &fz_image_store_type); + } +} + static void fz_mask_color_key(fz_pixmap *pix, int n, const int *colorkey) { @@ -671,7 +697,7 @@ fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subar keyp = fz_malloc_struct(ctx, fz_image_key); keyp->refs = 1; - keyp->image = fz_keep_image(ctx, image); + keyp->image = fz_keep_image_store_key(ctx, image); keyp->l2factor = l2factor; keyp->rect = key.rect; existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type); @@ -754,7 +780,7 @@ fz_new_image(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace, assert(size >= sizeof(fz_image)); image = Memento_label(fz_calloc(ctx, 1, size), "fz_image"); - FZ_INIT_STORABLE(image, 1, fz_drop_image_imp); + FZ_INIT_KEY_STORABLE(image, 1, fz_drop_image_imp); image->drop_image = drop; image->get_pixmap = get; image->get_size = get_size; diff --git a/source/fitz/store.c b/source/fitz/store.c index cad027bc..8d0a7bc4 100644 --- a/source/fitz/store.c +++ b/source/fitz/store.c @@ -81,6 +81,95 @@ fz_drop_storable(fz_context *ctx, const fz_storable *sc) s->drop(ctx, s); } +void *fz_keep_key_storable(fz_context *ctx, const fz_key_storable *sc) +{ + return fz_keep_storable(ctx, &sc->storable); +} + +int fz_drop_key_storable(fz_context *ctx, const fz_key_storable *sc) +{ + /* Explicitly drop const to allow us to use const + * sanely throughout the code. */ + fz_key_storable *s = (fz_key_storable *)sc; + int drop; + int only_refs_are_store_key_refs = 0; + + if (s == NULL) + return 0; + + if (s->storable.refs > 0) + (void)Memento_dropRef(s); + fz_lock(ctx, FZ_LOCK_ALLOC); + if (s->storable.refs > 0) + { + drop = --s->storable.refs == 0; + if (!drop && s->storable.refs == s->store_key_refs) + only_refs_are_store_key_refs = 1; + } + else + drop = 0; + fz_unlock(ctx, FZ_LOCK_ALLOC); + /* + 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. + */ + if (drop) + s->storable.drop(ctx, &s->storable); + return only_refs_are_store_key_refs; +} + +void *fz_keep_key_storable_key(fz_context *ctx, const fz_key_storable *sc) +{ + /* Explicitly drop const to allow us to use const + * sanely throughout the code. */ + fz_key_storable *s = (fz_key_storable *)sc; + + if (s == NULL) + return NULL; + + if (s->storable.refs > 0) + (void)Memento_takeRef(s); + fz_lock(ctx, FZ_LOCK_ALLOC); + if (s->storable.refs > 0) + { + ++s->storable.refs; + ++s->store_key_refs; + } + fz_unlock(ctx, FZ_LOCK_ALLOC); + return s; +} + +void fz_drop_key_storable_key(fz_context *ctx, const fz_key_storable *sc) +{ + /* Explicitly drop const to allow us to use const + * sanely throughout the code. */ + fz_key_storable *s = (fz_key_storable *)sc; + int drop; + + if (s == NULL) + return; + + if (s->storable.refs > 0) + (void)Memento_dropRef(s); + fz_lock(ctx, FZ_LOCK_ALLOC); + assert(s->store_key_refs > 0 && s->storable.refs >= s->store_key_refs); + drop = --s->storable.refs == 0; + --s->store_key_refs; + fz_unlock(ctx, FZ_LOCK_ALLOC); + /* + 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. + */ + if (drop) + s->storable.drop(ctx, &s->storable); +} + static void evict(fz_context *ctx, fz_item *item) { @@ -636,3 +725,36 @@ fz_shrink_store(fz_context *ctx, unsigned int percent) return success; } + +void fz_filter_store(fz_context *ctx, fz_store_filter_fn *fn, void *arg, fz_store_type *type) +{ + fz_store *store; + fz_item *item, *prev; + + if (ctx == NULL) + return; + store = ctx->store; + if (store == NULL) + return; + + fz_lock(ctx, FZ_LOCK_ALLOC); + + /* Free the items */ + for (item = store->tail; item; item = prev) + { + prev = item->prev; + if (item->type != type) + continue; + + if (fn(ctx, arg, item->key)) + { + /* Free this item */ + evict(ctx, item); /* Drops then retakes lock */ + + /* Have to restart search again, as prev may no longer + * be valid due to release of lock in evict. */ + prev = store->tail; + } + } + fz_unlock(ctx, FZ_LOCK_ALLOC); +} diff --git a/source/gprf/gprf-doc.c b/source/gprf/gprf-doc.c index 5ca14aea..56570db0 100644 --- a/source/gprf/gprf-doc.c +++ b/source/gprf/gprf-doc.c @@ -467,7 +467,7 @@ fz_new_gprf_image(fz_context *ctx, gprf_page *page, int imagenum, fz_off_t offse h = GPRF_TILESIZE; } - FZ_INIT_STORABLE(&image->super, 1, fz_drop_image_gprf_imp); + FZ_INIT_KEY_STORABLE(&image->super, 1, fz_drop_image_gprf_imp); image->super.w = w; image->super.h = h; image->super.n = 4; /* Always RGB + Alpha */ |