diff src/glyphs.c @ 450:98528da0b7fc r21-2-40

Import from CVS: tag r21-2-40
author cvs
date Mon, 13 Aug 2007 11:39:20 +0200
parents 3078fd1074e8
children 3d3049ae1304
line wrap: on
line diff
--- a/src/glyphs.c	Mon Aug 13 11:38:26 2007 +0200
+++ b/src/glyphs.c	Mon Aug 13 11:39:20 2007 +0200
@@ -382,7 +382,7 @@
 	 skip it. */
       if (!(dest_mask &
 	    IIFORMAT_METH (decode_image_instantiator_format
-			   (XVECTOR_DATA (typevec)[0], ERROR_ME),
+			   (INSTANTIATOR_TYPE (typevec), ERROR_ME),
 			   possible_dest_types, ())))
 	continue;
       if (fast_string_match (exp, 0, data, 0, -1, 0, ERROR_ME, 0) >= 0)
@@ -689,7 +689,7 @@
   int governing_domain;
 
   struct image_instantiator_methods *meths =
-    decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
+    decode_image_instantiator_format (INSTANTIATOR_TYPE (instantiator),
 				      ERROR_ME);
   governing_domain = IIFORMAT_METH_OR_GIVEN (meths, governing_domain, (),
 					     GOVERNING_DOMAIN_DEVICE);
@@ -742,7 +742,7 @@
 
     GCPRO1 (instantiator);
 
-    meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
+    meths = decode_image_instantiator_format (INSTANTIATOR_TYPE (instantiator),
 					      ERROR_ME);
     RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize,
 					    (instantiator, contype, dest_mask),
@@ -765,20 +765,20 @@
   struct gcpro gcpro1;
 
   GCPRO1 (ii);
-  if (!valid_image_instantiator_format_p (XVECTOR_DATA (instantiator)[0],
+  if (!valid_image_instantiator_format_p (INSTANTIATOR_TYPE (instantiator),
 					  DOMAIN_DEVICE (governing_domain)))
     signal_simple_error
       ("Image instantiator format is invalid in this locale.",
        instantiator);
 
-  meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
+  meths = decode_image_instantiator_format (INSTANTIATOR_TYPE (instantiator),
 					    ERROR_ME);
   MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg,
 					    pointer_bg, dest_mask, domain));
 
   /* Now do device specific instantiation. */
   device_meths = decode_device_ii_format (DOMAIN_DEVICE (governing_domain),
-					  XVECTOR_DATA (instantiator)[0],
+					  INSTANTIATOR_TYPE (instantiator),
 					  ERROR_ME_NOT);
 
   if (!HAS_IIFORMAT_METH_P (meths, instantiate)
@@ -1469,7 +1469,7 @@
   GCPRO1 (data);
   /* After normalizing the data, it's always either an image instance (which
      we filtered out above) or a vector. */
-  if (EQ (XVECTOR_DATA (data)[0], Qinherit))
+  if (EQ (INSTANTIATOR_TYPE (data), Qinherit))
     signal_simple_error ("Inheritance not allowed here", data);
   governing_domain =
     get_image_instantiator_governing_domain (data, domain);
@@ -1992,9 +1992,6 @@
   assert (XIMAGE_INSTANCE_YOFFSET (image_instance) >= 0
 	  && XIMAGE_INSTANCE_XOFFSET (image_instance) >= 0);
 
-  type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
-  meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
-
   /* If geometry is unspecified then get some reasonable values for it. */
   if (width == IMAGE_UNSPECIFIED_GEOMETRY
       ||
@@ -2002,20 +1999,11 @@
     {
       int dwidth = IMAGE_UNSPECIFIED_GEOMETRY;
       int dheight = IMAGE_UNSPECIFIED_GEOMETRY;
-
       /* Get the desired geometry. */
-      if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
-	{
-	  IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
-						 IMAGE_DESIRED_GEOMETRY,
-						 domain));
-	}
-      else
-	{
-	  dwidth = IMAGE_INSTANCE_WIDTH (ii);
-	  dheight = IMAGE_INSTANCE_HEIGHT (ii);
-	}
-
+      image_instance_query_geometry (image_instance,
+				     &dwidth, &dheight,
+				     IMAGE_DESIRED_GEOMETRY,
+				     domain);
       /* Compare with allowed geometry. */
       if (width == IMAGE_UNSPECIFIED_GEOMETRY)
 	width = dwidth;
@@ -2042,12 +2030,15 @@
   IMAGE_INSTANCE_WIDTH (ii) = width;
   IMAGE_INSTANCE_HEIGHT (ii) = height;
 
-  if (IIFORMAT_METH_OR_GIVEN (meths, layout,
-			      (image_instance, width, height, xoffset, yoffset,
-			       domain), 1))
-    /* Do not clear the dirty flag here - redisplay will do this for
-       us at the end. */
-    IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
+  type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
+  meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
+
+  MAYBE_IIFORMAT_METH (meths, layout,
+		       (image_instance, width, height, xoffset, yoffset,
+			domain));
+  /* Do not clear the dirty flag here - redisplay will do this for
+     us at the end. */
+  IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
 }
 
 /* Update an image instance from its changed instantiator. */
@@ -3054,6 +3045,44 @@
   mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image));
 }
 
+static int
+instantiator_eq_equal (Lisp_Object obj1, Lisp_Object obj2)
+{
+  if (EQ (obj1, obj2))
+    return 1;
+
+  else if (CONSP (obj1) && CONSP (obj2))
+    {
+      return instantiator_eq_equal (XCAR (obj1), XCAR (obj2))
+	&&
+	instantiator_eq_equal (XCDR (obj1), XCDR (obj2));
+    }
+  return 0;
+}
+
+static hashcode_t
+instantiator_eq_hash (Lisp_Object obj)
+{
+  if (CONSP (obj))
+    {
+      /* no point in worrying about tail recursion, since we're not
+	 going very deep */
+      return HASH2 (instantiator_eq_hash (XCAR (obj)),
+		    instantiator_eq_hash (XCDR (obj)));
+    }
+  return LISP_HASH (obj);
+}
+
+/* We need a special hash table for storing image instances. */
+Lisp_Object
+make_image_instance_cache_hash_table (void)
+{
+  return make_general_lisp_hash_table
+    (instantiator_eq_hash, instantiator_eq_equal,
+     30, -1.0, -1.0,
+     HASH_TABLE_KEY_CAR_VALUE_WEAK);
+}
+
 static Lisp_Object
 image_instantiate_cache_result (Lisp_Object locative)
 {
@@ -3110,7 +3139,7 @@
 			       instantiator, domain);
     }
   else if (VECTORP (instantiator)
-	   && EQ (XVECTOR_DATA (instantiator)[0], Qinherit))
+	   && EQ (INSTANTIATOR_TYPE (instantiator), Qinherit))
     {
       assert (XVECTOR_LENGTH (instantiator) == 3);
       return (FACE_PROPERTY_INSTANCE
@@ -3121,7 +3150,8 @@
     {
       Lisp_Object instance = Qnil;
       Lisp_Object subtable = Qnil;
-      Lisp_Object ls3 = Qnil;
+      /* #### Should this be GCPRO'd? */
+      Lisp_Object hash_key = Qnil;
       Lisp_Object pointer_fg = Qnil;
       Lisp_Object pointer_bg = Qnil;
       Lisp_Object governing_domain =
@@ -3139,8 +3169,15 @@
 	{
 	  pointer_fg = FACE_FOREGROUND (Vpointer_face, domain);
 	  pointer_bg = FACE_BACKGROUND (Vpointer_face, domain);
-	  ls3 = list3 (glyph, pointer_fg, pointer_bg);
+	  hash_key = list4 (glyph, INSTANTIATOR_TYPE (instantiator), 
+			    pointer_fg, pointer_bg);
 	}
+      else
+	/* We cannot simply key on the glyph since fallbacks could use
+	   the same glyph but have a totally different instantiator
+	   type. Thus we key on the glyph and the type (but not any
+	   other parts of the instantiator. */
+	hash_key = list2 (glyph, INSTANTIATOR_TYPE (instantiator));
 
       /* First look in the device cache. */
       if (DEVICEP (governing_domain))
@@ -3167,20 +3204,15 @@
 		 have to use EQUAL because we massaged the
 		 instantiator into a cons3 also containing the
 		 foreground and background of the pointer face.  */
-
-	      subtable = make_lisp_hash_table
-		(20, pointerp ? HASH_TABLE_KEY_CAR_WEAK
-		 : HASH_TABLE_KEY_WEAK,
-		 pointerp ? HASH_TABLE_EQUAL
-		 : HASH_TABLE_EQ);
+	      subtable = make_image_instance_cache_hash_table ();
+
 	      Fputhash (make_int (dest_mask), subtable,
 			XDEVICE (governing_domain)->image_instance_cache);
 	      instance = Qunbound;
 	    }
 	  else
 	    {
-	      instance = Fgethash (pointerp ? ls3 : glyph,
-				   subtable, Qunbound);
+	      instance = Fgethash (hash_key, subtable, Qunbound);
 	    }
 	}
       else if (WINDOWP (governing_domain))
@@ -3188,7 +3220,7 @@
 	  /* Subwindows have a per-window cache and have to be treated
 	     differently. */
 	  instance =
-	    Fgethash (pointerp ? ls3 : glyph,
+	    Fgethash (hash_key,
 		      XWINDOW (governing_domain)->subwindow_instance_cache,
 		      Qunbound);
 	}
@@ -3201,7 +3233,7 @@
 	{
 	  Lisp_Object locative =
 	    noseeum_cons (Qnil,
-			  noseeum_cons (pointerp ? ls3 : glyph,
+			  noseeum_cons (hash_key,
 					DEVICEP (governing_domain) ? subtable
 					: XWINDOW (governing_domain)
 					->subwindow_instance_cache));
@@ -3234,7 +3266,7 @@
 #ifdef ERROR_CHECK_GLYPHS
 	  if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
 	      & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
-	    assert (EQ (Fgethash ((pointerp ? ls3 : glyph),
+	    assert (EQ (Fgethash (hash_key,
 				  XWINDOW (governing_domain)
 				  ->subwindow_instance_cache,
 				  Qunbound), instance));
@@ -3258,7 +3290,7 @@
 	     possible to make changes that don't get reflected in the
 	     display. */
 	  update_image_instance (instance, instantiator);
-	  free_list (ls3);
+	  free_list (hash_key);
 	}
 
 #ifdef ERROR_CHECK_GLYPHS