* image.c: Shrink memory needed for animation cache.
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 19 Aug 2013 20:47:27 +0000 (13:47 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 19 Aug 2013 20:47:27 +0000 (13:47 -0700)
(SIGNATURE_DIGESTSIZE): New constant.
(struct animation_cache): Make 'signature' a fixed size array of bytes.
(imagemagick_create_cache): Copy the signature.  This saves
several KB of memory that ImageMagick wastes per signature.
Don't bother updating the update_time, as the caller does that now.
(imagemagick_prune_animation_cache): Don't destroy the signature, as
it's a fixed size struct member now.
(imagemagick_get_animation_cache): Always destroy the signature,
as it's now imagemagick_create_cache's responsibility to copy it.
Avoid duplicate calls to strcmp and to imagemagick_create_cache,
and use memcmp rather than strcmp.
eassert that ImageMagick returns a signature of the specified length.

src/ChangeLog
src/image.c

index 2171f2b..d0bafd3 100644 (file)
@@ -1,3 +1,19 @@
+2013-08-19  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * image.c: Shrink memory needed for animation cache.
+       (SIGNATURE_DIGESTSIZE): New constant.
+       (struct animation_cache): Make 'signature' a fixed size array of bytes.
+       (imagemagick_create_cache): Copy the signature.  This saves
+       several KB of memory that ImageMagick wastes per signature.
+       Don't bother updating the update_time, as the caller does that now.
+       (imagemagick_prune_animation_cache): Don't destroy the signature, as
+       it's a fixed size struct member now.
+       (imagemagick_get_animation_cache): Always destroy the signature,
+       as it's now imagemagick_create_cache's responsibility to copy it.
+       Avoid duplicate calls to strcmp and to imagemagick_create_cache,
+       and use memcmp rather than strcmp.
+       eassert that ImageMagick returns a signature of the specified length.
+
 2013-08-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * image.c (imagemagick_get_animation_cache): Don't segfault on
index 7a6323a..4970d40 100644 (file)
@@ -7876,13 +7876,17 @@ imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent])
    separate from the image cache, because the images may be scaled
    before display. */
 
+/* Size of ImageMagick image signatures, in bytes.  It's SHA-256 as a
+   hex string, so it's 256 bits represented via 4 bits per byte.  */
+enum { SIGNATURE_DIGESTSIZE = 256 / 4 };
+
 struct animation_cache
 {
-  char *signature;
   MagickWand *wand;
   int index;
   EMACS_TIME update_time;
   struct animation_cache *next;
+  char signature[SIGNATURE_DIGESTSIZE];
 };
 
 static struct animation_cache *animation_cache = NULL;
@@ -7891,11 +7895,10 @@ static struct animation_cache *
 imagemagick_create_cache (char *signature)
 {
   struct animation_cache *cache = xmalloc (sizeof *cache);
-  cache->signature = signature;
   cache->wand = 0;
   cache->index = 0;
   cache->next = 0;
-  cache->update_time = current_emacs_time ();
+  memcpy (cache->signature, signature, SIGNATURE_DIGESTSIZE);
   return cache;
 }
 
@@ -7914,7 +7917,6 @@ imagemagick_prune_animation_cache (void)
        pcache = &cache->next;
       else
        {
-         DestroyString (cache->signature);
          if (cache->wand)
            DestroyMagickWand (cache->wand);
          *pcache = cache->next;
@@ -7928,24 +7930,22 @@ imagemagick_get_animation_cache (MagickWand *wand)
 {
   char *signature = MagickGetImageSignature (wand);
   struct animation_cache *cache;
+  struct animation_cache **pcache = &animation_cache;
 
+  eassert (strlen (signature) == SIGNATURE_DIGESTSIZE);
   imagemagick_prune_animation_cache ();
-  cache = animation_cache;
 
-  if (! cache)
+  while (1)
     {
-      animation_cache = imagemagick_create_cache (signature);
-      return animation_cache;
-    }
-
-  while (strcmp (signature, cache->signature) &&
-        cache->next)
-    cache = cache->next;
-
-  if (strcmp (signature, cache->signature))
-    {
-      cache->next = imagemagick_create_cache (signature);
-      return cache->next;
+      cache = *pcache;
+      if (! cache)
+       {
+          *pcache = cache = imagemagick_create_cache (signature);
+          break;
+        }
+      if (memcmp (signature, cache->signature, SIGNATURE_DIGESTSIZE) == 0)
+       break;
+      pcache = &cache->next;
     }
 
   DestroyString (signature);