aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Magne Ingebrigtsen2013-08-16 16:54:46 +0200
committerLars Magne Ingebrigtsen2013-08-16 16:54:46 +0200
commit274ff63f7f7d19c3eb0c365ed7f8347131b9f62e (patch)
tree544f622625ad3724d2e26b0ecaa25d16140337cf /src
parente4043ba039b64f2fd91cc3ec950b3d23031a87ce (diff)
downloademacs-274ff63f7f7d19c3eb0c365ed7f8347131b9f62e.tar.gz
emacs-274ff63f7f7d19c3eb0c365ed7f8347131b9f62e.zip
* image.c: Implement an ImageMagick per-image cache.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog4
-rw-r--r--src/image.c108
2 files changed, 101 insertions, 11 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index ab21a65a805..d5c97748d1a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
12013-08-16 Lars Magne Ingebrigtsen <larsi@gnus.org>
2
3 * image.c: Implement an ImageMagick per-image cache.
4
12013-08-16 Xue Fuqiao <xfq.free@gmail.com> 52013-08-16 Xue Fuqiao <xfq.free@gmail.com>
2 6
3 * editfns.c (insert_before_markers): Mention overlay in the doc string. 7 * editfns.c (insert_before_markers): Mention overlay in the doc string.
diff --git a/src/image.c b/src/image.c
index 6dc997aa4d0..082cc6a762a 100644
--- a/src/image.c
+++ b/src/image.c
@@ -7869,10 +7869,91 @@ imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent])
7869 follow. If following images have non-transparent colors, these are 7869 follow. If following images have non-transparent colors, these are
7870 composed "on top" of the master image. So, in general, one has to 7870 composed "on top" of the master image. So, in general, one has to
7871 compute ann the preceding images to be able to display a particular 7871 compute ann the preceding images to be able to display a particular
7872 sub-image. */ 7872 sub-image.
7873 7873
7874static MagickWand *animation_cache = NULL; 7874 Computing all the preceding images is too slow, so we maintain a
7875static int animation_index = 0; 7875 cache of previously computed images. We have to maintain a cache
7876 separate from the image cache, because the images may be scaled
7877 before display. */
7878
7879struct animation_cache
7880{
7881 char *signature;
7882 MagickWand *wand;
7883 int index;
7884 EMACS_TIME update_time;
7885 struct animation_cache *next;
7886};
7887
7888static struct animation_cache *animation_cache = NULL;
7889
7890struct animation_cache *
7891imagemagick_create_cache (char *signature)
7892{
7893 struct animation_cache *cache = xzalloc (sizeof (struct animation_cache));
7894 cache->signature = signature;
7895 cache->update_time = current_emacs_time ();
7896 return cache;
7897}
7898
7899/* Discard cached images that haven't been used for a minute. */
7900void
7901imagemagick_prune_animation_cache ()
7902{
7903 struct animation_cache *cache = animation_cache;
7904 struct animation_cache *prev;
7905 EMACS_TIME old = sub_emacs_time (current_emacs_time (),
7906 EMACS_TIME_FROM_DOUBLE (60));
7907
7908 while (cache)
7909 {
7910 if (EMACS_TIME_LT (cache->update_time, old))
7911 {
7912 struct animation_cache *this_cache = cache;
7913 free (cache->signature);
7914 if (cache->wand)
7915 DestroyMagickWand (cache->wand);
7916 if (prev)
7917 prev->next = cache->next;
7918 else
7919 animation_cache = cache->next;
7920 cache = cache->next;
7921 free (this_cache);
7922 }
7923 else {
7924 prev = cache;
7925 cache = cache->next;
7926 }
7927 }
7928}
7929
7930struct animation_cache *
7931imagemagick_get_animation_cache (MagickWand *wand)
7932{
7933 char *signature = MagickGetImageSignature (wand);
7934 struct animation_cache *cache = animation_cache;
7935
7936 imagemagick_prune_animation_cache ();
7937
7938 if (! cache)
7939 {
7940 animation_cache = imagemagick_create_cache (signature);
7941 return animation_cache;
7942 }
7943
7944 while (strcmp(signature, cache->signature) &&
7945 cache->next)
7946 cache = cache->next;
7947
7948 if (strcmp(signature, cache->signature))
7949 {
7950 cache->next = imagemagick_create_cache (signature);
7951 return cache->next;
7952 }
7953
7954 cache->update_time = current_emacs_time ();
7955 return cache;
7956}
7876 7957
7877static MagickWand * 7958static MagickWand *
7878imagemagick_compute_animated_image (MagickWand *super_wand, int ino) 7959imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
@@ -7880,18 +7961,23 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
7880 int i; 7961 int i;
7881 MagickWand *composite_wand; 7962 MagickWand *composite_wand;
7882 size_t dest_width, dest_height; 7963 size_t dest_width, dest_height;
7964 struct animation_cache *cache = imagemagick_get_animation_cache (super_wand);
7883 7965
7884 MagickSetIteratorIndex (super_wand, 0); 7966 MagickSetIteratorIndex (super_wand, 0);
7885 7967
7886 if (ino == 0 || animation_cache == NULL) 7968 if (ino == 0 || cache->wand == NULL || cache->index > ino)
7887 composite_wand = MagickGetImage (super_wand); 7969 {
7970 composite_wand = MagickGetImage (super_wand);
7971 if (cache->wand)
7972 DestroyMagickWand (cache->wand);
7973 }
7888 else 7974 else
7889 composite_wand = animation_cache; 7975 composite_wand = cache->wand;
7890 7976
7891 dest_width = MagickGetImageWidth (composite_wand); 7977 dest_width = MagickGetImageWidth (composite_wand);
7892 dest_height = MagickGetImageHeight (composite_wand); 7978 dest_height = MagickGetImageHeight (composite_wand);
7893 7979
7894 for (i = max (1, animation_index + 1); i <= ino; i++) 7980 for (i = max (1, cache->index + 1); i <= ino; i++)
7895 { 7981 {
7896 MagickWand *sub_wand; 7982 MagickWand *sub_wand;
7897 PixelIterator *source_iterator, *dest_iterator; 7983 PixelIterator *source_iterator, *dest_iterator;
@@ -7916,7 +8002,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
7916 { 8002 {
7917 DestroyMagickWand (composite_wand); 8003 DestroyMagickWand (composite_wand);
7918 DestroyMagickWand (sub_wand); 8004 DestroyMagickWand (sub_wand);
7919 animation_cache = NULL; 8005 cache->wand = NULL;
7920 image_error ("Imagemagick pixel iterator creation failed", 8006 image_error ("Imagemagick pixel iterator creation failed",
7921 Qnil, Qnil); 8007 Qnil, Qnil);
7922 return NULL; 8008 return NULL;
@@ -7928,7 +8014,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
7928 DestroyMagickWand (composite_wand); 8014 DestroyMagickWand (composite_wand);
7929 DestroyMagickWand (sub_wand); 8015 DestroyMagickWand (sub_wand);
7930 DestroyPixelIterator (source_iterator); 8016 DestroyPixelIterator (source_iterator);
7931 animation_cache = NULL; 8017 cache->wand = NULL;
7932 image_error ("Imagemagick pixel iterator creation failed", 8018 image_error ("Imagemagick pixel iterator creation failed",
7933 Qnil, Qnil); 8019 Qnil, Qnil);
7934 return NULL; 8020 return NULL;
@@ -7979,8 +8065,8 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
7979 8065
7980 /* Cache a copy for the next iteration. The current wand will be 8066 /* Cache a copy for the next iteration. The current wand will be
7981 destroyed by the caller. */ 8067 destroyed by the caller. */
7982 animation_cache = CloneMagickWand (composite_wand); 8068 cache->wand = CloneMagickWand (composite_wand);
7983 animation_index = ino; 8069 cache->index = ino;
7984 8070
7985 return composite_wand; 8071 return composite_wand;
7986} 8072}