+ /* If we don't have sane values then we cannot layout at this point and
+ must just return. */
+ if (width == IMAGE_UNSPECIFIED_GEOMETRY
+ ||
+ height == IMAGE_UNSPECIFIED_GEOMETRY)
+ return;
+
+ /* At this point width and height should contain sane values. Thus
+ we set the glyph geometry and lay it out. */
+ if (IMAGE_INSTANCE_WIDTH (ii) != width
+ ||
+ IMAGE_INSTANCE_HEIGHT (ii) != height)
+ {
+ IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
+ }
+
+ IMAGE_INSTANCE_WIDTH (ii) = width;
+ IMAGE_INSTANCE_HEIGHT (ii) = height;
+
+ 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. */
+static void
+update_image_instance (Lisp_Object image_instance,
+ Lisp_Object instantiator)
+{
+ struct image_instantiator_methods* meths;
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+ ERROR_CHECK_IMAGE_INSTANCE (image_instance);
+
+ if (NOTHING_IMAGE_INSTANCEP (image_instance))
+ return;
+
+ assert (!internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, 0)
+ || (internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, 0)
+ && internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, -10)));
+
+ /* If the instantiator is identical then do nothing. We must use
+ equal here because the specifier code copies the instantiator. */
+ if (!internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, 0))
+ {
+ /* Extract the changed properties so that device / format
+ methods only have to cope with these. We assume that
+ normalization has already been done. */
+ Lisp_Object diffs = find_instantiator_differences
+ (instantiator,
+ IMAGE_INSTANCE_INSTANTIATOR (ii));
+ Lisp_Object type = encode_image_instance_type
+ (IMAGE_INSTANCE_TYPE (ii));
+ struct gcpro gcpro1;
+ GCPRO1 (diffs);
+
+ /* try device specific methods first ... */
+ meths = decode_device_ii_format (image_instance_device (image_instance),
+ type, ERROR_ME_NOT);
+ MAYBE_IIFORMAT_METH (meths, update, (image_instance, diffs));
+ /* ... then format specific methods ... */
+ meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
+ MAYBE_IIFORMAT_METH (meths, update, (image_instance, diffs));
+
+ /* Instance and therefore glyph has changed so mark as dirty.
+ If we don't do this output optimizations will assume the
+ glyph is unchanged. */
+ set_image_instance_dirty_p (image_instance, 1);
+ /* Structure has changed. */
+ IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
+
+ UNGCPRO;
+ }
+ /* We should now have a consistent instantiator so keep a record of
+ it. It is important that we don't actually update the window
+ system widgets here - we must do that when redisplay tells us
+ to.
+
+ #### should we delay doing this until the display is up-to-date
+ also? */
+ IMAGE_INSTANCE_INSTANTIATOR (ii) = instantiator;
+}
+
+/*
+ * Mark image instance in W as dirty if (a) W's faces have changed and
+ * (b) GLYPH_OR_II instance in W is a string.
+ *
+ * Return non-zero if instance has been marked dirty.
+ */
+int
+invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w)
+{
+ if (XFRAME(WINDOW_FRAME(w))->faces_changed)
+ {
+ Lisp_Object image = glyph_or_ii;
+
+ if (GLYPHP (glyph_or_ii))
+ {
+ Lisp_Object window;
+ XSETWINDOW (window, w);
+ image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1);
+ }
+
+ if (TEXT_IMAGE_INSTANCEP (image))
+ {
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image);
+ IMAGE_INSTANCE_DIRTYP (ii) = 1;
+ IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
+ if (GLYPHP (glyph_or_ii))
+ XGLYPH_DIRTYP (glyph_or_ii) = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+\f
+/************************************************************************/
+/* error helpers */
+/************************************************************************/
+DOESNT_RETURN
+signal_image_error (const char *reason, Lisp_Object frob)
+{
+ signal_error (Qimage_conversion_error,
+ list2 (build_translated_string (reason), frob));
+}
+
+DOESNT_RETURN
+signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1)
+{
+ signal_error (Qimage_conversion_error,
+ list3 (build_translated_string (reason), frob0, frob1));
+}
+
+/****************************************************************************
+ * nothing *
+ ****************************************************************************/
+
+static int
+nothing_possible_dest_types (void)
+{
+ return IMAGE_NOTHING_MASK;
+}
+
+static void
+nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+ if (dest_mask & IMAGE_NOTHING_MASK)
+ {
+ IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
+ IMAGE_INSTANCE_HEIGHT (ii) = 0;
+ IMAGE_INSTANCE_WIDTH (ii) = 0;
+ }
+ else
+ incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK);
+}
+
+\f
+/****************************************************************************
+ * inherit *
+ ****************************************************************************/
+
+static void
+inherit_validate (Lisp_Object instantiator)
+{
+ face_must_be_present (instantiator);
+}
+
+static Lisp_Object
+inherit_normalize (Lisp_Object inst, Lisp_Object console_type,
+ Lisp_Object dest_mask)
+{
+ Lisp_Object face;
+
+ assert (XVECTOR_LENGTH (inst) == 3);
+ face = XVECTOR_DATA (inst)[2];
+ if (!FACEP (face))
+ inst = vector3 (Qinherit, Q_face, Fget_face (face));
+ return inst;
+}
+
+static int
+inherit_possible_dest_types (void)