changeset 65891:d0d10499b708

Rename member for_overlaps_p in struct glyph_string to for_overlaps. (get_glyph_string_clip_rects): New function created from get_glyph_string_clip_rect. Set clipping rectangles according to the value of for_overlaps. Enable to store multiple clipping rectangles. (get_glyph_string_clip_rect): Use get_glyph_string_clip_rects. (fill_composite_glyph_string, fill_glyph_string, draw_glyphs): Rename argument OVERLAPS_P to OVERLAPS. All uses in macros changed. (x_fix_overlapping_area): Add OVERLAPS arg. Pass it to draw_glyphs. (draw_phys_cursor_glyph): Set width of erased cursor to use it for calculating clipping rectangles later. Call x_fix_overlapping_area with new OVERLAPS arg to draw only erased cursor area. (expose_overlaps): Call x_fix_overlapping_area with new OVERLAPS arg to draw overlaps in both preceding and succeeding rows.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Fri, 07 Oct 2005 07:39:17 +0000
parents 1a7a619caf97
children 41fc0bf568be
files src/xdisp.c
diffstat 1 files changed, 132 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Fri Oct 07 07:38:47 2005 +0000
+++ b/src/xdisp.c	Fri Oct 07 07:39:17 2005 +0000
@@ -1768,15 +1768,20 @@
 }
 
 /* EXPORT:
-   Return in *R the clipping rectangle for glyph string S.  */
-
-void
-get_glyph_string_clip_rect (s, nr)
+   Return in RECTS[] at most N clipping rectangles for glyph string S.
+   Return the number of stored rectangles.  */
+
+int
+get_glyph_string_clip_rects (s, rects, n)
      struct glyph_string *s;
-     NativeRectangle *nr;
+     NativeRectangle *rects;
+     int n;
 {
   XRectangle r;
 
+  if (n <= 0)
+    return 0;
+
   if (s->row->full_width_p)
     {
       /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
@@ -1819,10 +1824,27 @@
   /* 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.  */
-  if (s->for_overlaps_p)
+  if (s->for_overlaps)
     {
       r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
       r.height = window_text_bottom_y (s->w) - r.y;
+
+      /* Alas, the above simple strategy does not work for the
+	 environments with anti-aliased text: if the same text is
+	 drawn onto the same place multiple times, it gets thicker.
+	 If the overlap we are processing is for the erased cursor, we
+	 take the intersection with the rectagle of the cursor.  */
+      if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
+	{
+	  XRectangle rc, r_save = r;
+
+	  rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
+	  rc.y = s->w->phys_cursor.y;
+	  rc.width = s->w->phys_cursor_width;
+	  rc.height = s->w->phys_cursor_height;
+
+	  x_intersect_rectangles (&r_save, &rc, &r);
+	}
     }
   else
     {
@@ -1881,11 +1903,71 @@
 	}
     }
 
+  if ((s->for_overlaps & OVERLAPS_BOTH) == 0
+      || (s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1)
+    {
 #ifdef CONVERT_FROM_XRECT
-  CONVERT_FROM_XRECT (r, *nr);
+      CONVERT_FROM_XRECT (r, *rects);
+#else
+      *rects = r;
+#endif
+      return 1;
+    }
+  else
+    {
+      /* If we are processing overlapping and allowed to return
+	 multiple clipping rectangles, we exclude the row of the glyph
+	 string from the clipping rectangle.  This is to avoid drawing
+	 the same text on the environment with anti-aliasing.  */
+#ifdef CONVERT_FROM_XRECT
+      XRectangle rs[2];
 #else
-  *nr = r;
-#endif
+      XRectangle *rs = rects;
+#endif
+      int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
+
+      if (s->for_overlaps & OVERLAPS_PRED)
+	{
+	  rs[i] = r;
+	  if (r.y + r.height > row_y)
+	    if (r.y < row_y)
+	      rs[i].height = row_y - r.y;
+	    else
+	      rs[i].height = 0;
+	  i++;
+	}
+      if (s->for_overlaps & OVERLAPS_SUCC)
+	{
+	  rs[i] = r;
+	  if (r.y < row_y + s->row->visible_height)
+	    if (r.y + r.height > row_y + s->row->visible_height)
+	      {
+		rs[i].y = row_y + s->row->visible_height;
+		rs[i].height = r.y + r.height - rs[i].y;
+	      }
+	    else
+	      rs[i].height = 0;
+	  i++;
+	}
+
+      n = i;
+#ifdef CONVERT_FROM_XRECT
+      for (i = 0; i < n; i++)
+	CONVERT_FROM_XRECT (rs[i], rects[i]);
+#endif
+      return n;
+    }
+}
+
+/* EXPORT:
+   Return in *NR the clipping rectangle for glyph string S.  */
+
+void
+get_glyph_string_clip_rect (s, nr)
+     struct glyph_string *s;
+     NativeRectangle *nr;
+{
+  get_glyph_string_clip_rects (s, nr, 1);
 }
 
 
@@ -18023,22 +18105,23 @@
 
    FACES is an array of faces for all components of this composition.
    S->gidx is the index of the first component for S.
-   OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its physical height for clipping.
+
+   OVERLAPS non-zero means S should draw the foreground only, and use
+   its physical height for clipping.  See also draw_glyphs.
 
    Value is the index of a component not in S.  */
 
 static int
-fill_composite_glyph_string (s, faces, overlaps_p)
+fill_composite_glyph_string (s, faces, overlaps)
      struct glyph_string *s;
      struct face **faces;
-     int overlaps_p;
+     int overlaps;
 {
   int i;
 
   xassert (s);
 
-  s->for_overlaps_p = overlaps_p;
+  s->for_overlaps = overlaps;
 
   s->face = faces[s->gidx];
   s->font = s->face->font;
@@ -18082,16 +18165,16 @@
 
    FACE_ID is the face id of the string.  START is the index of the
    first glyph to consider, END is the index of the last + 1.
-   OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its physical height for clipping.
+   OVERLAPS non-zero means S should draw the foreground only, and use
+   its physical height for clipping.  See also draw_glyphs.
 
    Value is the index of the first glyph not in S.  */
 
 static int
-fill_glyph_string (s, face_id, start, end, overlaps_p)
+fill_glyph_string (s, face_id, start, end, overlaps)
      struct glyph_string *s;
      int face_id;
-     int start, end, overlaps_p;
+     int start, end, overlaps;
 {
   struct glyph *glyph, *last;
   int voffset;
@@ -18101,7 +18184,7 @@
   xassert (s->nchars == 0);
   xassert (start >= 0 && end > start);
 
-  s->for_overlaps_p = overlaps_p,
+  s->for_overlaps = overlaps,
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
@@ -18578,7 +18661,7 @@
 	 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);	   \
 	 append_glyph_string (&HEAD, &TAIL, s);				   \
 	 s->x = (X);							   \
-	 START = fill_glyph_string (s, face_id, START, END, overlaps_p);   \
+	 START = fill_glyph_string (s, face_id, START, END, overlaps);   \
        }								   \
      while (0)
 
@@ -18631,7 +18714,7 @@
 	if (n == 0)							  \
 	  first_s = s;							  \
 									  \
-	n = fill_composite_glyph_string (s, faces, overlaps_p);		  \
+	n = fill_composite_glyph_string (s, faces, overlaps);		  \
       }									  \
     									  \
     ++START;								  \
@@ -18700,20 +18783,26 @@
    DRAW_IMAGE_SUNKEN	draw an image with a sunken relief around it
    DRAW_IMAGE_RAISED	draw an image with a raised relief around it
 
-   If OVERLAPS_P is non-zero, draw only the foreground of characters
-   and clip to the physical height of ROW.
+   If OVERLAPS is non-zero, draw only the foreground of characters and
+   clip to the physical height of ROW.  Non-zero value also defines
+   the overlapping part to be drawn:
+
+   OVERLAPS_PRED		overlap with preceding rows
+   OVERLAPS_SUCC		overlap with succeeding rows
+   OVERLAPS_BOTH		overlap with both preceding/succeeding rows
+   OVERLAPS_ERASED_CURSOR	overlap with erased cursor area
 
    Value is the x-position reached, relative to AREA of W.  */
 
 static int
-draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
+draw_glyphs (w, x, row, area, start, end, hl, overlaps)
      struct window *w;
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
      int start, end;
      enum draw_glyphs_face hl;
-     int overlaps_p;
+     int overlaps;
 {
   struct glyph_string *head, *tail;
   struct glyph_string *s;
@@ -18762,7 +18851,7 @@
   /* If there are any glyphs with lbearing < 0 or rbearing > width in
      the row, redraw some glyphs in front or following the glyph
      strings built above.  */
-  if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
+  if (head && !overlaps && row->contains_overlapping_glyphs_p)
     {
       int dummy_x = 0;
       struct glyph_string *h, *t;
@@ -18855,7 +18944,7 @@
       /* When drawing overlapping rows, only the glyph strings'
 	 foreground is drawn, which doesn't erase a cursor
 	 completely. */
-      && !overlaps_p)
+      && !overlaps)
     {
       int x0 = clip_head ? clip_head->x : (head ? head->x : x);
       int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
@@ -20588,13 +20677,15 @@
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* EXPORT for RIF:
-   Fix the display of area AREA of overlapping row ROW in window W.  */
-
-void
-x_fix_overlapping_area (w, row, area)
+   Fix the display of area AREA of overlapping row ROW in window W
+   with respect to the overlapping part OVERLAPS.  */
+
+void
+x_fix_overlapping_area (w, row, area, overlaps)
      struct window *w;
      struct glyph_row *row;
      enum glyph_row_area area;
+     int overlaps;
 {
   int i, x;
 
@@ -20617,7 +20708,7 @@
 
 	  draw_glyphs (w, start_x, row, area,
 		       start, i,
-		       DRAW_NORMAL_TEXT, 1);
+		       DRAW_NORMAL_TEXT, overlaps);
 	}
       else
 	{
@@ -20659,13 +20750,17 @@
 	 are redrawn.  */
       else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
 	{
+	  w->phys_cursor_width = x1 - w->phys_cursor.x;
+
 	  if (row > w->current_matrix->rows
 	      && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
-	    x_fix_overlapping_area (w, row - 1, TEXT_AREA);
+	    x_fix_overlapping_area (w, row - 1, TEXT_AREA,
+				    OVERLAPS_ERASED_CURSOR);
 
 	  if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
 	      && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
-	    x_fix_overlapping_area (w, row + 1, TEXT_AREA);
+	    x_fix_overlapping_area (w, row + 1, TEXT_AREA,
+				    OVERLAPS_ERASED_CURSOR);
 	}
     }
 }
@@ -22456,13 +22551,13 @@
 	xassert (row->enabled_p && !row->mode_line_p);
 
 	if (row->used[LEFT_MARGIN_AREA])
-	  x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+	  x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
 
 	if (row->used[TEXT_AREA])
-	  x_fix_overlapping_area (w, row, TEXT_AREA);
+	  x_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
 
 	if (row->used[RIGHT_MARGIN_AREA])
-	  x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+	  x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
       }
 }