diff options
| author | Po Lu | 2023-09-26 09:30:04 +0800 |
|---|---|---|
| committer | Po Lu | 2023-09-26 09:30:04 +0800 |
| commit | 50281b4007062533ca18f98deeac6b7d923d1922 (patch) | |
| tree | 6197c28acbff0a1d340c3ab5a46281b895caf8b0 /src | |
| parent | 50e913c956924fe7b6799ed1d42e02a707b83eb6 (diff) | |
| download | emacs-50281b4007062533ca18f98deeac6b7d923d1922.tar.gz emacs-50281b4007062533ca18f98deeac6b7d923d1922.zip | |
Properly clip overlaid fringe bitmaps
* src/xterm.c (x_draw_fringe_bitmap): Save clip rectangle from
x_clip_to_row, and draw only the intersection between it and the
fringe bitmap, for if the bitmap is overlaid, the clip mask will
override the clip rectangle.
(x_clip_to_row): New argument *RECT_RETURN. All callers
changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/xterm.c b/src/xterm.c index bd779cb21bf..33e12d48912 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -1167,7 +1167,7 @@ static struct terminal *x_create_terminal (struct x_display_info *); | |||
| 1167 | static void x_frame_rehighlight (struct x_display_info *); | 1167 | static void x_frame_rehighlight (struct x_display_info *); |
| 1168 | 1168 | ||
| 1169 | static void x_clip_to_row (struct window *, struct glyph_row *, | 1169 | static void x_clip_to_row (struct window *, struct glyph_row *, |
| 1170 | enum glyph_row_area, GC); | 1170 | enum glyph_row_area, GC, XRectangle *); |
| 1171 | static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int); | 1171 | static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int); |
| 1172 | static struct frame *x_window_to_frame (struct x_display_info *, int); | 1172 | static struct frame *x_window_to_frame (struct x_display_info *, int); |
| 1173 | static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, | 1173 | static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, |
| @@ -7842,9 +7842,10 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 7842 | Display *display = FRAME_X_DISPLAY (f); | 7842 | Display *display = FRAME_X_DISPLAY (f); |
| 7843 | GC gc = f->output_data.x->normal_gc; | 7843 | GC gc = f->output_data.x->normal_gc; |
| 7844 | struct face *face = p->face; | 7844 | struct face *face = p->face; |
| 7845 | XRectangle clip_rect; | ||
| 7845 | 7846 | ||
| 7846 | /* Must clip because of partially visible lines. */ | 7847 | /* Must clip because of partially visible lines. */ |
| 7847 | x_clip_to_row (w, row, ANY_AREA, gc); | 7848 | x_clip_to_row (w, row, ANY_AREA, gc, &clip_rect); |
| 7848 | 7849 | ||
| 7849 | if (p->bx >= 0 && !p->overlay_p) | 7850 | if (p->bx >= 0 && !p->overlay_p) |
| 7850 | { | 7851 | { |
| @@ -7914,6 +7915,30 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 7914 | 7915 | ||
| 7915 | memset (&attrs, 0, sizeof attrs); | 7916 | memset (&attrs, 0, sizeof attrs); |
| 7916 | #endif | 7917 | #endif |
| 7918 | XRectangle image_rect, dest; | ||
| 7919 | int window_x, window_y, window_width; | ||
| 7920 | int px, py, pwidth, pheight; | ||
| 7921 | |||
| 7922 | /* Intersect the destination rectangle with that of the row. | ||
| 7923 | Setting a clip mask overrides the clip rectangles provided by | ||
| 7924 | x_clip_to_row, so clipping must be performed by hand. */ | ||
| 7925 | |||
| 7926 | image_rect.x = p->x; | ||
| 7927 | image_rect.y = p->y; | ||
| 7928 | image_rect.width = p->wd; | ||
| 7929 | image_rect.height = p->h; | ||
| 7930 | |||
| 7931 | if (!gui_intersect_rectangles (&clip_rect, &image_rect, &dest)) | ||
| 7932 | /* The entire destination rectangle falls outside the row. */ | ||
| 7933 | goto undo_clip; | ||
| 7934 | |||
| 7935 | /* Extrapolate the source rectangle from the difference between | ||
| 7936 | the destination and image rectangles. */ | ||
| 7937 | |||
| 7938 | px = dest.x - image_rect.x; | ||
| 7939 | py = dest.y - image_rect.y; | ||
| 7940 | pwidth = dest.width; | ||
| 7941 | pheight = dest.height; | ||
| 7917 | 7942 | ||
| 7918 | if (p->wd > 8) | 7943 | if (p->wd > 8) |
| 7919 | bits = (char *) (p->bits + p->dh); | 7944 | bits = (char *) (p->bits + p->dh); |
| @@ -7985,15 +8010,16 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 7985 | x_xr_apply_ext_clip (f, gc); | 8010 | x_xr_apply_ext_clip (f, gc); |
| 7986 | XRenderComposite (display, PictOpSrc, picture, | 8011 | XRenderComposite (display, PictOpSrc, picture, |
| 7987 | None, FRAME_X_PICTURE (f), | 8012 | None, FRAME_X_PICTURE (f), |
| 7988 | 0, 0, 0, 0, p->x, p->y, p->wd, p->h); | 8013 | px, py, px, py, dest.x, dest.y, |
| 8014 | pwidth, pheight); | ||
| 7989 | x_xr_reset_ext_clip (f); | 8015 | x_xr_reset_ext_clip (f); |
| 7990 | 8016 | ||
| 7991 | XRenderFreePicture (display, picture); | 8017 | XRenderFreePicture (display, picture); |
| 7992 | } | 8018 | } |
| 7993 | else | 8019 | else |
| 7994 | #endif | 8020 | #endif |
| 7995 | XCopyArea (display, pixmap, drawable, gc, 0, 0, | 8021 | XCopyArea (display, pixmap, drawable, gc, px, py, |
| 7996 | p->wd, p->h, p->x, p->y); | 8022 | pwidth, pheight, dest.x, dest.y); |
| 7997 | XFreePixmap (display, pixmap); | 8023 | XFreePixmap (display, pixmap); |
| 7998 | 8024 | ||
| 7999 | if (p->overlay_p) | 8025 | if (p->overlay_p) |
| @@ -8003,6 +8029,8 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 8003 | XFreePixmap (display, clipmask); | 8029 | XFreePixmap (display, clipmask); |
| 8004 | } | 8030 | } |
| 8005 | } | 8031 | } |
| 8032 | |||
| 8033 | undo_clip: | ||
| 8006 | #endif /* not USE_CAIRO */ | 8034 | #endif /* not USE_CAIRO */ |
| 8007 | 8035 | ||
| 8008 | x_reset_clip_rectangles (f, gc); | 8036 | x_reset_clip_rectangles (f, gc); |
| @@ -25646,13 +25674,17 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 25646 | /* Set clipping for output in glyph row ROW. W is the window in which | 25674 | /* Set clipping for output in glyph row ROW. W is the window in which |
| 25647 | we operate. GC is the graphics context to set clipping in. | 25675 | we operate. GC is the graphics context to set clipping in. |
| 25648 | 25676 | ||
| 25677 | If RECT_RETURN is non-NULL, return the clip rectangle within | ||
| 25678 | *RECT_RETURN. | ||
| 25679 | |||
| 25649 | ROW may be a text row or, e.g., a mode line. Text rows must be | 25680 | ROW may be a text row or, e.g., a mode line. Text rows must be |
| 25650 | clipped to the interior of the window dedicated to text display, | 25681 | clipped to the interior of the window dedicated to text display, |
| 25651 | mode lines must be clipped to the whole window. */ | 25682 | mode lines must be clipped to the whole window. */ |
| 25652 | 25683 | ||
| 25653 | static void | 25684 | static void |
| 25654 | x_clip_to_row (struct window *w, struct glyph_row *row, | 25685 | x_clip_to_row (struct window *w, struct glyph_row *row, |
| 25655 | enum glyph_row_area area, GC gc) | 25686 | enum glyph_row_area area, GC gc, |
| 25687 | XRectangle *rect_return) | ||
| 25656 | { | 25688 | { |
| 25657 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 25689 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 25658 | XRectangle clip_rect; | 25690 | XRectangle clip_rect; |
| @@ -25667,6 +25699,9 @@ x_clip_to_row (struct window *w, struct glyph_row *row, | |||
| 25667 | clip_rect.height = row->visible_height; | 25699 | clip_rect.height = row->visible_height; |
| 25668 | 25700 | ||
| 25669 | x_set_clip_rectangles (f, gc, &clip_rect, 1); | 25701 | x_set_clip_rectangles (f, gc, &clip_rect, 1); |
| 25702 | |||
| 25703 | if (rect_return) | ||
| 25704 | *rect_return = clip_rect; | ||
| 25670 | } | 25705 | } |
| 25671 | 25706 | ||
| 25672 | 25707 | ||
| @@ -25715,7 +25750,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) | |||
| 25715 | wd -= 1; | 25750 | wd -= 1; |
| 25716 | } | 25751 | } |
| 25717 | /* Set clipping, draw the rectangle, and reset clipping again. */ | 25752 | /* Set clipping, draw the rectangle, and reset clipping again. */ |
| 25718 | x_clip_to_row (w, row, TEXT_AREA, gc); | 25753 | x_clip_to_row (w, row, TEXT_AREA, gc, NULL); |
| 25719 | x_draw_rectangle (f, gc, x, y, wd, h - 1); | 25754 | x_draw_rectangle (f, gc, x, y, wd, h - 1); |
| 25720 | x_reset_clip_rectangles (f, gc); | 25755 | x_reset_clip_rectangles (f, gc); |
| 25721 | } | 25756 | } |
| @@ -25785,7 +25820,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text | |||
| 25785 | FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc; | 25820 | FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc; |
| 25786 | } | 25821 | } |
| 25787 | 25822 | ||
| 25788 | x_clip_to_row (w, row, TEXT_AREA, gc); | 25823 | x_clip_to_row (w, row, TEXT_AREA, gc, NULL); |
| 25789 | 25824 | ||
| 25790 | if (kind == BAR_CURSOR) | 25825 | if (kind == BAR_CURSOR) |
| 25791 | { | 25826 | { |