mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-22 05:51:11 -07:00
Prune animation cache when images are no longer reachable
* lisp/image.el (image-animate-timeout): Eject cached animated images that are no longer reachable (bug#56546). * src/image.c (Fclear_image_cache): Allow specifying a cached animated image to eject. (gif_load, webp_load): Adjust what to use as the caching key -- the identity of the list itself is apparently changed by some callers.
This commit is contained in:
parent
4c542747bd
commit
564f6c171e
2 changed files with 42 additions and 14 deletions
|
|
@ -966,9 +966,10 @@ for the animation speed. A negative value means to animate in reverse."
|
|||
(plist-put (cdr image) :animate-tardiness
|
||||
(+ (* (plist-get (cdr image) :animate-tardiness) 0.9)
|
||||
(float-time (time-since target-time))))
|
||||
(let ((buffer (plist-get (cdr image) :animate-buffer))
|
||||
(position (plist-get (cdr image) :animate-position)))
|
||||
(when (and (buffer-live-p buffer)
|
||||
(let* ((buffer (plist-get (cdr image) :animate-buffer))
|
||||
(position (plist-get (cdr image) :animate-position))
|
||||
(continue-animation
|
||||
(and (buffer-live-p buffer)
|
||||
;; If we have a :animate-position setting, the caller
|
||||
;; has requested that the animation be stopped if the
|
||||
;; image is no longer displayed in the buffer.
|
||||
|
|
@ -985,7 +986,13 @@ for the animation speed. A negative value means to animate in reverse."
|
|||
(or (< (plist-get (cdr image) :animate-tardiness) 2)
|
||||
(progn
|
||||
(message "Stopping animation; animation possibly too big")
|
||||
nil)))
|
||||
nil)))))
|
||||
(if (not continue-animation)
|
||||
;; Eject from the animation cache since we've decided not to
|
||||
;; keep updating it. This helps stop unbounded RAM usage when
|
||||
;; doing, for instance, `g' in an eww buffer with animated
|
||||
;; images.
|
||||
(clear-image-cache nil image)
|
||||
(let* ((time (prog1 (current-time)
|
||||
(image-show-frame image n t)))
|
||||
(speed (image-animate-get-speed image))
|
||||
|
|
|
|||
41
src/image.c
41
src/image.c
|
|
@ -186,6 +186,10 @@ static void free_color_table (void);
|
|||
static unsigned long *colors_in_color_table (int *n);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_WEBP) || defined (HAVE_GIF)
|
||||
static void anim_prune_animation_cache (Lisp_Object);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CAIRO
|
||||
|
||||
static Emacs_Pix_Container
|
||||
|
|
@ -2127,14 +2131,27 @@ clear_image_caches (Lisp_Object filter)
|
|||
}
|
||||
|
||||
DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
|
||||
0, 1, 0,
|
||||
0, 2, 0,
|
||||
doc: /* Clear the image cache.
|
||||
FILTER nil or a frame means clear all images in the selected frame.
|
||||
FILTER t means clear the image caches of all frames.
|
||||
Anything else means clear only those images that refer to FILTER,
|
||||
which is then usually a filename. */)
|
||||
(Lisp_Object filter)
|
||||
which is then usually a filename.
|
||||
|
||||
This function also clears the image animation cache. If
|
||||
ANIMATION-CACHE is non-nil, only the image spec `eq' with
|
||||
ANIMATION-CACHE is removed, and other image cache entries are not
|
||||
evicted. */)
|
||||
(Lisp_Object filter, Lisp_Object animation_cache)
|
||||
{
|
||||
if (!NILP (animation_cache))
|
||||
{
|
||||
#if defined (HAVE_WEBP) || defined (HAVE_GIF)
|
||||
anim_prune_animation_cache (XCDR (animation_cache));
|
||||
#endif
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (! (NILP (filter) || FRAMEP (filter)))
|
||||
clear_image_caches (filter);
|
||||
else
|
||||
|
|
@ -3048,9 +3065,11 @@ anim_create_cache (Lisp_Object spec)
|
|||
}
|
||||
|
||||
/* Discard cached images that haven't been used for a minute. If
|
||||
CLEAR, remove all animation cache entries. */
|
||||
CLEAR is t, remove all animation cache entries. If CLEAR is
|
||||
anything other than nil or t, only remove the entries that have a
|
||||
spec `eq' to CLEAR. */
|
||||
static void
|
||||
anim_prune_animation_cache (bool clear)
|
||||
anim_prune_animation_cache (Lisp_Object clear)
|
||||
{
|
||||
struct anim_cache **pcache = &anim_cache;
|
||||
struct timespec old = timespec_sub (current_timespec (),
|
||||
|
|
@ -3059,7 +3078,9 @@ anim_prune_animation_cache (bool clear)
|
|||
while (*pcache)
|
||||
{
|
||||
struct anim_cache *cache = *pcache;
|
||||
if (clear || timespec_cmp (old, cache->update_time) > 0)
|
||||
if (EQ (clear, Qt)
|
||||
|| (EQ (clear, Qnil) && timespec_cmp (old, cache->update_time) > 0)
|
||||
|| EQ (clear, cache->spec))
|
||||
{
|
||||
if (cache->handle)
|
||||
cache->destructor (cache);
|
||||
|
|
@ -3079,7 +3100,7 @@ anim_get_animation_cache (Lisp_Object spec)
|
|||
struct anim_cache *cache;
|
||||
struct anim_cache **pcache = &anim_cache;
|
||||
|
||||
anim_prune_animation_cache (false);
|
||||
anim_prune_animation_cache (Qnil);
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
|
@ -9020,7 +9041,7 @@ gif_load (struct frame *f, struct image *img)
|
|||
if (!NILP (image_number))
|
||||
{
|
||||
/* If this is an animated image, create a cache for it. */
|
||||
cache = anim_get_animation_cache (img->spec);
|
||||
cache = anim_get_animation_cache (XCDR (img->spec));
|
||||
/* We have an old cache entry, so use it. */
|
||||
if (cache->handle)
|
||||
{
|
||||
|
|
@ -9722,7 +9743,7 @@ webp_load (struct frame *f, struct image *img)
|
|||
/* Animated image. */
|
||||
int timestamp;
|
||||
|
||||
struct anim_cache* cache = anim_get_animation_cache (img->spec);
|
||||
struct anim_cache* cache = anim_get_animation_cache (XCDR (img->spec));
|
||||
/* Get the next frame from the animation cache. */
|
||||
if (cache->handle && cache->index == idx - 1)
|
||||
{
|
||||
|
|
@ -11998,7 +12019,7 @@ void
|
|||
image_prune_animation_caches (bool clear)
|
||||
{
|
||||
#if defined (HAVE_WEBP) || defined (HAVE_GIF)
|
||||
anim_prune_animation_cache (clear);
|
||||
anim_prune_animation_cache (clear? Qt: Qnil);
|
||||
#endif
|
||||
#ifdef HAVE_IMAGEMAGICK
|
||||
imagemagick_prune_animation_cache (clear);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue