From a66678fd3c23322bdebbe285086e9a6d9db1593d Mon Sep 17 00:00:00 2001 From: YAMAMOTO Mitsuharu Date: Fri, 7 Oct 2005 07:39:17 +0000 Subject: [PATCH] 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. --- src/xdisp.c | 161 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 128 insertions(+), 33 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index 2dd48757470..9e29bfa0e46 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1768,15 +1768,20 @@ frame_to_window_pixel_xy (w, x, y) } /* EXPORT: - Return in *R the clipping rectangle for glyph string S. */ + Return in RECTS[] at most N clipping rectangles for glyph string S. + Return the number of stored rectangles. */ -void -get_glyph_string_clip_rect (s, nr) +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 @@ get_glyph_string_clip_rect (s, nr) /* 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 @@ get_glyph_string_clip_rect (s, nr) } } + 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 - *nr = r; + *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 + 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 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p) 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 @@ fill_composite_glyph_string (s, faces, overlaps_p) 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 @@ fill_glyph_string (s, face_id, start, end, overlaps_p) 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 @@ compute_overhangs_and_x (s, x, backward_p) 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 @@ compute_overhangs_and_x (s, x, backward_p) 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 @@ compute_overhangs_and_x (s, x, backward_p) 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 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) /* 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 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) /* 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 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1) #ifdef HAVE_WINDOW_SYSTEM /* EXPORT for RIF: - Fix the display of area AREA of overlapping row ROW in window W. */ + 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) +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 @@ x_fix_overlapping_area (w, row, area) draw_glyphs (w, start_x, row, area, start, i, - DRAW_NORMAL_TEXT, 1); + DRAW_NORMAL_TEXT, overlaps); } else { @@ -20659,13 +20750,17 @@ draw_phys_cursor_glyph (w, row, hl) 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 @@ expose_overlaps (w, first_overlapping_row, last_overlapping_row) 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); } } -- 2.39.2