diff options
| author | Lars Ingebrigtsen | 2022-07-14 18:58:12 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-07-14 18:59:09 +0200 |
| commit | 564f6c171eeaef4dea4b4fc2524c0b082dfbb531 (patch) | |
| tree | 014595873d94947428e4a1a604f0d7602d5d51ea /src | |
| parent | 4c542747bd40f3098a20aafe001889607f044188 (diff) | |
| download | emacs-564f6c171eeaef4dea4b4fc2524c0b082dfbb531.tar.gz emacs-564f6c171eeaef4dea4b4fc2524c0b082dfbb531.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/image.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/src/image.c b/src/image.c index ba2a1f4294e..f5004c2c4c7 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -186,6 +186,10 @@ static void free_color_table (void); | |||
| 186 | static unsigned long *colors_in_color_table (int *n); | 186 | static unsigned long *colors_in_color_table (int *n); |
| 187 | #endif | 187 | #endif |
| 188 | 188 | ||
| 189 | #if defined (HAVE_WEBP) || defined (HAVE_GIF) | ||
| 190 | static void anim_prune_animation_cache (Lisp_Object); | ||
| 191 | #endif | ||
| 192 | |||
| 189 | #ifdef USE_CAIRO | 193 | #ifdef USE_CAIRO |
| 190 | 194 | ||
| 191 | static Emacs_Pix_Container | 195 | static Emacs_Pix_Container |
| @@ -2127,14 +2131,27 @@ clear_image_caches (Lisp_Object filter) | |||
| 2127 | } | 2131 | } |
| 2128 | 2132 | ||
| 2129 | DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache, | 2133 | DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache, |
| 2130 | 0, 1, 0, | 2134 | 0, 2, 0, |
| 2131 | doc: /* Clear the image cache. | 2135 | doc: /* Clear the image cache. |
| 2132 | FILTER nil or a frame means clear all images in the selected frame. | 2136 | FILTER nil or a frame means clear all images in the selected frame. |
| 2133 | FILTER t means clear the image caches of all frames. | 2137 | FILTER t means clear the image caches of all frames. |
| 2134 | Anything else means clear only those images that refer to FILTER, | 2138 | Anything else means clear only those images that refer to FILTER, |
| 2135 | which is then usually a filename. */) | 2139 | which is then usually a filename. |
| 2136 | (Lisp_Object filter) | 2140 | |
| 2141 | This function also clears the image animation cache. If | ||
| 2142 | ANIMATION-CACHE is non-nil, only the image spec `eq' with | ||
| 2143 | ANIMATION-CACHE is removed, and other image cache entries are not | ||
| 2144 | evicted. */) | ||
| 2145 | (Lisp_Object filter, Lisp_Object animation_cache) | ||
| 2137 | { | 2146 | { |
| 2147 | if (!NILP (animation_cache)) | ||
| 2148 | { | ||
| 2149 | #if defined (HAVE_WEBP) || defined (HAVE_GIF) | ||
| 2150 | anim_prune_animation_cache (XCDR (animation_cache)); | ||
| 2151 | #endif | ||
| 2152 | return Qnil; | ||
| 2153 | } | ||
| 2154 | |||
| 2138 | if (! (NILP (filter) || FRAMEP (filter))) | 2155 | if (! (NILP (filter) || FRAMEP (filter))) |
| 2139 | clear_image_caches (filter); | 2156 | clear_image_caches (filter); |
| 2140 | else | 2157 | else |
| @@ -3048,9 +3065,11 @@ anim_create_cache (Lisp_Object spec) | |||
| 3048 | } | 3065 | } |
| 3049 | 3066 | ||
| 3050 | /* Discard cached images that haven't been used for a minute. If | 3067 | /* Discard cached images that haven't been used for a minute. If |
| 3051 | CLEAR, remove all animation cache entries. */ | 3068 | CLEAR is t, remove all animation cache entries. If CLEAR is |
| 3069 | anything other than nil or t, only remove the entries that have a | ||
| 3070 | spec `eq' to CLEAR. */ | ||
| 3052 | static void | 3071 | static void |
| 3053 | anim_prune_animation_cache (bool clear) | 3072 | anim_prune_animation_cache (Lisp_Object clear) |
| 3054 | { | 3073 | { |
| 3055 | struct anim_cache **pcache = &anim_cache; | 3074 | struct anim_cache **pcache = &anim_cache; |
| 3056 | struct timespec old = timespec_sub (current_timespec (), | 3075 | struct timespec old = timespec_sub (current_timespec (), |
| @@ -3059,7 +3078,9 @@ anim_prune_animation_cache (bool clear) | |||
| 3059 | while (*pcache) | 3078 | while (*pcache) |
| 3060 | { | 3079 | { |
| 3061 | struct anim_cache *cache = *pcache; | 3080 | struct anim_cache *cache = *pcache; |
| 3062 | if (clear || timespec_cmp (old, cache->update_time) > 0) | 3081 | if (EQ (clear, Qt) |
| 3082 | || (EQ (clear, Qnil) && timespec_cmp (old, cache->update_time) > 0) | ||
| 3083 | || EQ (clear, cache->spec)) | ||
| 3063 | { | 3084 | { |
| 3064 | if (cache->handle) | 3085 | if (cache->handle) |
| 3065 | cache->destructor (cache); | 3086 | cache->destructor (cache); |
| @@ -3079,7 +3100,7 @@ anim_get_animation_cache (Lisp_Object spec) | |||
| 3079 | struct anim_cache *cache; | 3100 | struct anim_cache *cache; |
| 3080 | struct anim_cache **pcache = &anim_cache; | 3101 | struct anim_cache **pcache = &anim_cache; |
| 3081 | 3102 | ||
| 3082 | anim_prune_animation_cache (false); | 3103 | anim_prune_animation_cache (Qnil); |
| 3083 | 3104 | ||
| 3084 | while (1) | 3105 | while (1) |
| 3085 | { | 3106 | { |
| @@ -9020,7 +9041,7 @@ gif_load (struct frame *f, struct image *img) | |||
| 9020 | if (!NILP (image_number)) | 9041 | if (!NILP (image_number)) |
| 9021 | { | 9042 | { |
| 9022 | /* If this is an animated image, create a cache for it. */ | 9043 | /* If this is an animated image, create a cache for it. */ |
| 9023 | cache = anim_get_animation_cache (img->spec); | 9044 | cache = anim_get_animation_cache (XCDR (img->spec)); |
| 9024 | /* We have an old cache entry, so use it. */ | 9045 | /* We have an old cache entry, so use it. */ |
| 9025 | if (cache->handle) | 9046 | if (cache->handle) |
| 9026 | { | 9047 | { |
| @@ -9722,7 +9743,7 @@ webp_load (struct frame *f, struct image *img) | |||
| 9722 | /* Animated image. */ | 9743 | /* Animated image. */ |
| 9723 | int timestamp; | 9744 | int timestamp; |
| 9724 | 9745 | ||
| 9725 | struct anim_cache* cache = anim_get_animation_cache (img->spec); | 9746 | struct anim_cache* cache = anim_get_animation_cache (XCDR (img->spec)); |
| 9726 | /* Get the next frame from the animation cache. */ | 9747 | /* Get the next frame from the animation cache. */ |
| 9727 | if (cache->handle && cache->index == idx - 1) | 9748 | if (cache->handle && cache->index == idx - 1) |
| 9728 | { | 9749 | { |
| @@ -11998,7 +12019,7 @@ void | |||
| 11998 | image_prune_animation_caches (bool clear) | 12019 | image_prune_animation_caches (bool clear) |
| 11999 | { | 12020 | { |
| 12000 | #if defined (HAVE_WEBP) || defined (HAVE_GIF) | 12021 | #if defined (HAVE_WEBP) || defined (HAVE_GIF) |
| 12001 | anim_prune_animation_cache (clear); | 12022 | anim_prune_animation_cache (clear? Qt: Qnil); |
| 12002 | #endif | 12023 | #endif |
| 12003 | #ifdef HAVE_IMAGEMAGICK | 12024 | #ifdef HAVE_IMAGEMAGICK |
| 12004 | imagemagick_prune_animation_cache (clear); | 12025 | imagemagick_prune_animation_cache (clear); |