+
+/************************************************************************/
+/* Geometry calculations */
+/************************************************************************/
+
+/* Find out desired geometry of the image instance. If there is no
+ special function then just return the width and / or height. */
+void
+image_instance_query_geometry (Lisp_Object image_instance,
+ unsigned int* width, unsigned int* height,
+ enum image_instance_geometry disp,
+ Lisp_Object domain)
+{
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Object type;
+ struct image_instantiator_methods* meths;
+
+ type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
+ meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
+
+ if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
+ {
+ IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
+ disp, domain));
+ }
+ else
+ {
+ if (width)
+ *width = IMAGE_INSTANCE_WIDTH (ii);
+ if (height)
+ *height = IMAGE_INSTANCE_HEIGHT (ii);
+ }
+}
+
+/* Layout the image instance using the provided dimensions. Layout
+ widgets are going to do different kinds of calculations to
+ determine what size to give things so we could make the layout
+ function relatively simple to take account of that. An alternative
+ approach is to consider separately the two cases, one where you
+ don't mind what size you have (normal widgets) and one where you
+ want to specifiy something (layout widgets). */
+void
+image_instance_layout (Lisp_Object image_instance,
+ unsigned int width, unsigned int height,
+ Lisp_Object domain)
+{
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Object type;
+ struct image_instantiator_methods* meths;
+
+ 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
+ ||
+ height == IMAGE_UNSPECIFIED_GEOMETRY)
+ {
+ unsigned int dwidth, dheight;
+
+ /* 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);
+ }
+
+ /* Compare with allowed geometry. */
+ if (width == IMAGE_UNSPECIFIED_GEOMETRY)
+ width = dwidth;
+ if (height == IMAGE_UNSPECIFIED_GEOMETRY)
+ height = dheight;
+ }
+
+ /* 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;
+
+ if (meths && HAS_IIFORMAT_METH_P (meths, layout))
+ {
+ IIFORMAT_METH (meths, layout, (image_instance, width, height, domain));
+ }
+ /* else no change to the geometry. */
+
+ /* Do not clear the dirty flag here - redisplay will do this for
+ us at the end. */
+ IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
+}
+
+/*
+ * 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;
+}
+