changeset 59718:d4cb255b034d

* dispextern.h (struct glyph_string): New members clip_head and clip_tail. * xdisp.c (get_glyph_string_clip_rect): Restrict horizontal clip region to the area between clip_head and clip_tail. (draw_glyphs): Record the area that need to be actually redrawn to the new variables clip_head and clip_tail when there are overhangs. Set values of these variables to the corresponding members in struct glyph_string. Refine x coordinates for * macgui.h (STORE_XCHARSETSTRUCT): New macro. * macterm.c (mac_compute_glyph_string_overhangs): Implement with QDTextBounds. (x_draw_glyph_string): Don't fill the background of the successor of a glyph with a right overhang if the successor will draw a cursor. (XLoadQueryFont): Obtain font metrics using QDTextBounds. (x_redisplay_interface): Add entry for compute_glyph_string_overhangs.
author Steven Tamm <steventamm@mac.com>
date Mon, 24 Jan 2005 17:59:36 +0000
parents 351ffb20ab9f
children b1adddb0ff32
files src/dispextern.h src/macgui.h src/macterm.c src/xdisp.c
diffstat 4 files changed, 122 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/src/dispextern.h	Mon Jan 24 13:22:29 2005 +0000
+++ b/src/dispextern.h	Mon Jan 24 17:59:36 2005 +0000
@@ -1193,6 +1193,11 @@
   /* Slice */
   struct glyph_slice slice;
 
+  /* Non-null means the horizontal clipping region starts from the
+     left edge of *clip_head, and ends with the right edge of
+     *clip_tail, not including their overhangs.  */
+  struct glyph_string *clip_head, *clip_tail;
+
   struct glyph_string *next, *prev;
 };
 
--- a/src/macgui.h	Mon Jan 24 13:22:29 2005 +0000
+++ b/src/macgui.h	Mon Jan 24 17:59:36 2005 +0000
@@ -92,6 +92,13 @@
   int descent;
 } XCharStruct;
 
+#define STORE_XCHARSTRUCT(xcs, w, bds)			\
+  ((xcs).width = (w),					\
+   (xcs).lbearing = (bds).left,				\
+   (xcs).rbearing = (bds).right,			\
+   (xcs).ascent = -(bds).top,				\
+   (xcs).descent = (bds).bottom)
+
 struct MacFontStruct {
   char *fontname;
 
--- a/src/macterm.c	Mon Jan 24 13:22:29 2005 +0000
+++ b/src/macterm.c	Mon Jan 24 17:59:36 2005 +0000
@@ -1991,20 +1991,33 @@
 mac_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-#if 0
-  /* MAC_TODO: XTextExtents16 does nothing yet... */
-
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
-    {
-      XCharStruct cs;
-      int direction, font_ascent, font_descent;
-      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
-		      &font_ascent, &font_descent, &cs);
-      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
-      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
-    }
-#endif
+  Rect r;
+  MacFontStruct *font = s->font;
+
+  TextFont (font->mac_fontnum);
+  TextSize (font->mac_fontsize);
+  TextFace (font->mac_fontface);
+
+  if (s->two_byte_p)
+    QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
+  else
+    {
+      int i;
+      char *buf = xmalloc (s->nchars);
+
+      if (buf == NULL)
+	SetRect (&r, 0, 0, 0, 0);
+      else
+	{
+	  for (i = 0; i < s->nchars; ++i)
+	    buf[i] = s->char2b[i].byte2;
+	  QDTextBounds (s->nchars, buf, &r);
+	  xfree (buf);
+	}
+    }
+
+  s->right_overhang = r.right > s->width ? r.right - s->width : 0;
+  s->left_overhang = r.left < 0 ? -r.left : 0;
 }
 
 
@@ -3072,10 +3085,12 @@
 {
   int relief_drawn_p = 0;
 
-  /* If S draws into the background of its successor, draw the
-     background of the successor first so that S can draw into it.
-     This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
+  /* If S draws into the background of its successor that does not
+     draw a cursor, draw the background of the successor first so that
+     S can draw into it.  This makes S->next use XDrawString instead
+     of XDrawImageString.  */
+  if (s->next && s->right_overhang && !s->for_overlaps_p
+      && s->next->hl != DRAW_CURSOR)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -6756,30 +6771,40 @@
        returns 15 for 12-point Monaco! */
     char_width = CharWidth ('m');
 
-  font->max_bounds.rbearing = char_width;
-  font->max_bounds.lbearing = 0;
-  font->max_bounds.width = char_width;
-  font->max_bounds.ascent = the_fontinfo.ascent;
-  font->max_bounds.descent = the_fontinfo.descent;
-
-  font->min_bounds = font->max_bounds;
-
-  if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
-    font->per_char = NULL;
+  if (is_two_byte_font)
+    {
+      font->per_char = NULL;
+
+      if (fontface & italic)
+	font->max_bounds.rbearing = char_width + 1;
+      else
+	font->max_bounds.rbearing = char_width;
+      font->max_bounds.lbearing = 0;
+      font->max_bounds.width = char_width;
+      font->max_bounds.ascent = the_fontinfo.ascent;
+      font->max_bounds.descent = the_fontinfo.descent;
+
+      font->min_bounds = font->max_bounds;
+    }
   else
     {
       font->per_char = (XCharStruct *)
 	xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
       {
-        int c, min_width, max_width;
+	int c, min_width, max_width;
+	Rect char_bounds, min_bounds, max_bounds;
+	char ch;
 
 	min_width = max_width = char_width;
+	SetRect (&min_bounds, -32767, -32767, 32767, 32767);
+	SetRect (&max_bounds, 0, 0, 0, 0);
         for (c = 0x20; c <= 0xff; c++)
           {
-	    font->per_char[c - 0x20] = font->max_bounds;
-	    char_width = CharWidth (c);
-	    font->per_char[c - 0x20].width = char_width;
-	    font->per_char[c - 0x20].rbearing = char_width;
+	    ch = c;
+	    char_width = CharWidth (ch);
+	    QDTextBounds (1, &ch, &char_bounds);
+	    STORE_XCHARSTRUCT (font->per_char[c - 0x20],
+			       char_width, char_bounds);
 	    /* Some Japanese fonts (in SJIS encoding) return 0 as the
 	       character width of 0x7f.  */
 	    if (char_width > 0)
@@ -6787,9 +6812,25 @@
 		min_width = min (min_width, char_width);
 		max_width = max (max_width, char_width);
 	      }
-            }
-	font->min_bounds.width = min_width;
-	font->max_bounds.width = max_width;
+	    if (!EmptyRect (&char_bounds))
+	      {
+		SetRect (&min_bounds,
+			 max (min_bounds.left, char_bounds.left),
+			 max (min_bounds.top, char_bounds.top),
+			 min (min_bounds.right, char_bounds.right),
+			 min (min_bounds.bottom, char_bounds.bottom));
+		UnionRect (&max_bounds, &char_bounds, &max_bounds);
+	      }
+	  }
+	STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
+	STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
+	if (min_width == max_width
+	    && max_bounds.left >= 0 && max_bounds.right <= max_width)
+	  {
+	    /* Fixed width and no overhangs.  */
+	    xfree (font->per_char);
+	    font->per_char = NULL;
+	  }
       }
     }
 
@@ -9693,7 +9734,7 @@
   0, /* destroy_fringe_bitmap */
   mac_per_char_metric,
   mac_encode_char,
-  NULL, /* mac_compute_glyph_string_overhangs */
+  mac_compute_glyph_string_overhangs,
   x_draw_glyph_string,
   mac_define_frame_cursor,
   mac_clear_frame_area,
--- a/src/xdisp.c	Mon Jan 24 13:22:29 2005 +0000
+++ b/src/xdisp.c	Mon Jan 24 17:59:36 2005 +0000
@@ -1786,6 +1786,24 @@
       r.height = s->row->visible_height;
     }
 
+  if (s->clip_head)
+    if (r.x < s->clip_head->x)
+      {
+	if (r.width >= s->clip_head->x - r.x)
+	  r.width -= s->clip_head->x - r.x;
+	else
+	  r.width = 0;
+	r.x = s->clip_head->x;
+      }
+  if (s->clip_tail)
+    if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
+      {
+	if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
+	  r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
+	else
+	  r.width = 0;
+      }
+
   /* If S draws overlapping rows, it's sufficient to use the top and
      bottom of the window for clipping because this glyph string
      intentionally draws over other lines.  */
@@ -18233,6 +18251,7 @@
 {
   struct glyph_string *head, *tail;
   struct glyph_string *s;
+  struct glyph_string *clip_head = NULL, *clip_tail = NULL;
   int last_x, area_width;
   int x_reached;
   int i, j;
@@ -18301,6 +18320,7 @@
 	  start = i;
 	  compute_overhangs_and_x (t, head->x, 1);
 	  prepend_glyph_string_lists (&head, &tail, h, t);
+	  clip_head = head;
 	}
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -18313,6 +18333,7 @@
       i = left_overwriting (head);
       if (i >= 0)
 	{
+	  clip_head = head;
 	  BUILD_GLYPH_STRINGS (i, start, h, t,
 			       DRAW_NORMAL_TEXT, dummy_x, last_x);
 	  for (s = h; s; s = s->next)
@@ -18332,6 +18353,7 @@
 			       DRAW_NORMAL_TEXT, x, last_x);
 	  compute_overhangs_and_x (h, tail->x + tail->width, 0);
 	  append_glyph_string_lists (&head, &tail, h, t);
+	  clip_tail = tail;
 	}
 
       /* Append glyph strings for glyphs following the last glyph
@@ -18342,6 +18364,7 @@
       i = right_overwriting (tail);
       if (i >= 0)
 	{
+	  clip_tail = tail;
 	  BUILD_GLYPH_STRINGS (end, i, h, t,
 			       DRAW_NORMAL_TEXT, x, last_x);
 	  for (s = h; s; s = s->next)
@@ -18349,6 +18372,12 @@
 	  compute_overhangs_and_x (h, tail->x + tail->width, 0);
 	  append_glyph_string_lists (&head, &tail, h, t);
 	}
+      if (clip_head || clip_tail)
+	for (s = head; s; s = s->next)
+	  {
+	    s->clip_head = clip_head;
+	    s->clip_tail = clip_tail;
+	  }
     }
 
   /* Draw all strings.  */
@@ -18362,8 +18391,9 @@
 	 completely. */
       && !overlaps_p)
     {
-      int x0 = head ? head->x : x;
-      int x1 = tail ? tail->x + tail->background_width : x;
+      int x0 = clip_head ? clip_head->x : (head ? head->x : x);
+      int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
+		: (tail ? tail->x + tail->background_width : x));
 
       int text_left = window_box_left (w, TEXT_AREA);
       x0 -= text_left;