Ever noticed that when there is a glyph with text instance and
a face, XEmacs does not recompute the glyph when face changes?
When increasing face font size, the text grows and gets clipped
by the rectangle which was the glyph instance size at the
moment of glyph creation. Reproduction: Copy the following lines
after the initial three in *scratch*, and execute the first 3.
Then, as you play with font size, glyph size does not change, so
there is either a gap or clipping at the right of the glyph.
(setq g (make-glyph [string :data "GlYpH!"]))
(setq e (make-extent 5 5))
(set-extent-begin-glyph e g)
(cons (glyph-width g) (glyph-height g))
(make-face-larger 'default)
(make-face-smaller 'default)
Unfortunately, it is not quite possible to update more specific
glyphs when a face changes. Even if faces tracked glyphs which
have this face as their face, it would not be possible to notice
glyph change when this face changes through inheritance. So I
update a glyph instance in a window when both frame faces marked
as changed and glyph instance in the window is text.
2000-01-29 Kirill 'Big K' Katsnelson <kkm(a)dtmx.com>
* glyphs.c (image_instance_layout): Mark image instance as clean
after layout.
(glyph_dirty_p): Removed redundant function.
(invalidate_glyph_geometry_maybe): Added.
(update_glyph_cachel_data): Call it.
* glyphs.h: Prototyped it.
* redisplay.c (add_glyph_rune): Call it.
(redisplay_window): Reset glyphs cachels when frame faces has
changed, thus forcing recomputation of built-in border glyphs.
Index: glyphs.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v
retrieving revision 1.23.2.43
diff -u -r1.23.2.43 glyphs.c
--- glyphs.c 2000/01/28 12:41:45 1.23.2.43
+++ glyphs.c 2000/01/30 00:34:27
@@ -1691,8 +1691,42 @@
IIFORMAT_METH (meths, layout, (image_instance, width, height, domain));
}
/* else no change to the geometry. */
+
+ XIMAGE_INSTANCE_DIRTYP (image_instance) = 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))
+ {
+ XIMAGE_INSTANCE_DIRTYP (image) = 1;
+ if (GLYPHP (glyph_or_ii))
+ XGLYPH_DIRTYP (glyph_or_ii) = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/************************************************************************/
/* error helpers */
@@ -3488,6 +3522,7 @@
Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
domain, errb, no_quit, 0,
Qzero);
+ assert (!UNBOUNDP (image_instance));
return image_instance;
}
@@ -3631,13 +3666,6 @@
return make_int (glyph_height (glyph, window));
}
-static unsigned int
-glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window)
-{
- return XIMAGE_INSTANCE_DIRTYP (glyph_image_instance_maybe
- (glyph_or_image, window));
-}
-
static void
set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
{
@@ -3767,17 +3795,25 @@
struct glyph_cachel *cachel)
{
if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)
- || XGLYPH_DIRTYP (cachel->glyph))
+ || XGLYPH_DIRTYP (cachel->glyph)
+ || XFRAME(WINDOW_FRAME(w))->faces_changed)
{
Lisp_Object window, instance;
XSETWINDOW (window, w);
cachel->glyph = glyph;
- /* Speed things up slightly by grabbing the glyph instantiation
- and passing it to the size functions. */
+ /* Speed things up slightly by grabbing the glyph instantiation
+ and passing it to the size functions. */
instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
- cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window);
+
+ /* Mark text instance of the glyph dirty if faces have changed,
+ because its geometry might have changed. */
+ invalidate_glyph_geometry_maybe (instance, w);
+
+ /* #### Do the following 2 lines buy us anything? --kkm */
+ XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance);
+ cachel->dirty = XGLYPH_DIRTYP (glyph);
cachel->width = glyph_width (instance, window);
cachel->ascent = glyph_ascent (instance, window);
cachel->descent = glyph_descent (instance, window);
Index: glyphs.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.h,v
retrieving revision 1.18.2.28
diff -u -r1.18.2.28 glyphs.h
--- glyphs.h 2000/01/25 09:15:43 1.18.2.28
+++ glyphs.h 2000/01/30 00:34:28
@@ -335,6 +335,7 @@
void image_instance_layout (Lisp_Object image_instance,
unsigned int width, unsigned int height,
Lisp_Object domain);
+int invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w);
DECLARE_DOESNT_RETURN (incompatible_image_types (Lisp_Object instantiator,
int given_dest_mask,
Index: redisplay.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay.c,v
retrieving revision 1.55.2.36
diff -u -r1.55.2.36 redisplay.c
--- redisplay.c 2000/01/26 12:34:04 1.55.2.36
+++ redisplay.c 2000/01/30 00:34:30
@@ -1524,6 +1524,10 @@
{
struct window *w = XWINDOW (data->window);
+ /* If window faces changed, and glyph instance is text, then
+ glyph sizes might have changed too */
+ invalidate_glyph_geometry_maybe (gb->glyph, w);
+
/* A nil extent indicates a special glyph (ex. truncator). */
if (NILP (gb->extent)
|| (pos_type == BEGIN_GLYPHS &&
@@ -5931,7 +5935,7 @@
the cache purely because glyphs have changed - this is now
handled by the dirty flag.*/
if ((!echo_active && b != window_display_buffer (w))
- || !Dynarr_length (w->glyph_cachels))
+ || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
reset_glyph_cachels (w);
else
mark_glyph_cachels_as_not_updated (w);