1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-26 07:00:35 -08:00

Fix X11 relief background clearning when hwidth is larger than vwidth

* src/xterm.c (x_fill_triangle, x_make_point, x_inside_rect_p):
New functions.
(x_draw_relief_rect): Complete rewrite.  Use more sensible
primitives.
This commit is contained in:
Po Lu 2022-05-10 16:50:10 +08:00
parent c7b48b61d0
commit e8d643eb83

View file

@ -7390,20 +7390,62 @@ x_setup_relief_colors (struct glyph_string *s)
}
}
#ifndef USE_CAIRO
static void
x_fill_triangle (struct frame *f, GC gc, XPoint point1,
XPoint point2, XPoint point3)
{
XPoint abc[3];
abc[0] = point1;
abc[1] = point2;
abc[2] = point3;
XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
gc, abc, 3, Convex, CoordModeOrigin);
}
static XPoint
x_make_point (int x, int y)
{
XPoint pt;
pt.x = x;
pt.y = y;
return pt;
}
static bool
x_inside_rect_p (XRectangle *rects, int nrects, int x, int y)
{
int i;
for (i = 0; i < nrects; ++i)
{
if (x >= rects[i].x && y >= rects[i].y
&& x < rects[i].x + rects[i].width
&& y < rects[i].y + rects[i].height)
return true;
}
return false;
}
#endif
/* Draw a relief on frame F inside the rectangle given by LEFT_X,
TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
to draw, it must be >= 0. RAISED_P means draw a raised
relief. LEFT_P means draw a relief on the left side of
the rectangle. RIGHT_P means draw a relief on the right
side of the rectangle. CLIP_RECT is the clipping rectangle to use
when drawing. */
TOP_Y, RIGHT_X, and BOTTOM_Y. VWIDTH and HWIDTH are respectively
the thickness of the vertical relief (left and right) and
horizontal relief (top and bottom) to draw, it must be >= 0.
RAISED_P means draw a raised relief. LEFT_P means draw a relief on
the left side of the rectangle. RIGHT_P means draw a relief on the
right side of the rectangle. CLIP_RECT is the clipping rectangle
to use when drawing. */
static void
x_draw_relief_rect (struct frame *f,
int left_x, int top_y, int right_x, int bottom_y,
int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
bool left_p, bool right_p,
x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
int bottom_y, int hwidth, int vwidth, bool raised_p,
bool top_p, bool bot_p, bool left_p, bool right_p,
XRectangle *clip_rect)
{
#ifdef USE_CAIRO
@ -7479,90 +7521,116 @@ x_draw_relief_rect (struct frame *f,
x_reset_clip_rectangles (f, top_left_gc);
x_reset_clip_rectangles (f, bottom_right_gc);
#else
Display *dpy = FRAME_X_DISPLAY (f);
Drawable drawable = FRAME_X_DRAWABLE (f);
int i;
GC gc;
if (raised_p)
gc = f->output_data.x->white_relief.gc;
else
gc = f->output_data.x->black_relief.gc;
XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
GC gc, white_gc, black_gc, normal_gc;
Drawable drawable;
Display *dpy;
/* This code is more complicated than it has to be, because of two
minor hacks to make the boxes look nicer: (i) if width > 1, draw
the outermost line using the black relief. (ii) Omit the four
corner pixels. */
/* Top. */
if (top_p)
{
if (hwidth == 1)
XDrawLine (dpy, drawable, gc,
left_x + left_p, top_y,
right_x + !right_p, top_y);
white_gc = f->output_data.x->white_relief.gc;
black_gc = f->output_data.x->black_relief.gc;
normal_gc = f->output_data.x->normal_gc;
for (i = 1; i < hwidth; ++i)
XDrawLine (dpy, drawable, gc,
left_x + i * left_p, top_y + i,
right_x + 1 - i * right_p, top_y + i);
}
drawable = FRAME_X_DRAWABLE (f);
dpy = FRAME_X_DISPLAY (f);
/* Left. */
if (left_p)
{
if (vwidth == 1)
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
x_set_clip_rectangles (f, white_gc, clip_rect, 1);
x_set_clip_rectangles (f, black_gc, clip_rect, 1);
for (i = 1; i < vwidth; ++i)
XDrawLine (dpy, drawable, gc,
left_x + i, top_y + (i + 1) * top_p,
left_x + i, bottom_y + 1 - (i + 1) * bot_p);
}
XSetClipMask (dpy, gc, None);
if (raised_p)
gc = f->output_data.x->black_relief.gc;
gc = white_gc;
else
gc = f->output_data.x->white_relief.gc;
XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
gc = black_gc;
/* Outermost top line. */
if (top_p && hwidth > 1)
XDrawLine (dpy, drawable, gc,
left_x + left_p, top_y,
right_x + !right_p, top_y);
/* Draw lines. */
/* Outermost left line. */
if (left_p && vwidth > 1)
XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
if (top_p)
x_fill_rectangle (f, gc, left_x, top_y,
right_x - left_x + 1, hwidth,
false);
if (left_p)
x_fill_rectangle (f, gc, left_x, top_y, vwidth,
bottom_y - top_y + 1, false);
if (raised_p)
gc = black_gc;
else
gc = white_gc;
/* Bottom. */
if (bot_p)
{
if (hwidth >= 1)
XDrawLine (dpy, drawable, gc,
left_x + left_p, bottom_y,
right_x + !right_p, bottom_y);
x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
right_x - left_x + 1, hwidth, false);
for (i = 1; i < hwidth; ++i)
XDrawLine (dpy, drawable, gc,
left_x + i * left_p, bottom_y - i,
right_x + 1 - i * right_p, bottom_y - i);
}
/* Right. */
if (right_p)
x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y,
vwidth, bottom_y - top_y + 1, false);
/* Draw corners. */
if (bot_p && left_p)
x_fill_triangle (f, raised_p ? white_gc : black_gc,
x_make_point (left_x, bottom_y - hwidth),
x_make_point (left_x + vwidth, bottom_y - hwidth),
x_make_point (left_x, bottom_y));
if (top_p && right_p)
x_fill_triangle (f, raised_p ? white_gc : black_gc,
x_make_point (right_x - vwidth, top_y),
x_make_point (right_x, top_y),
x_make_point (right_x - vwidth, top_y + hwidth));
/* Draw outer line. */
if (top_p && left_p && bot_p && right_p
&& hwidth > 1 && vwidth > 1)
x_draw_rectangle (f, black_gc, left_x, top_y,
right_x - left_x, top_y - bottom_y);
else
{
for (i = 0; i < vwidth; ++i)
XDrawLine (dpy, drawable, gc,
right_x - i, top_y + (i + 1) * top_p,
right_x - i, bottom_y + 1 - (i + 1) * bot_p);
if (top_p && hwidth > 1)
XDrawLine (dpy, drawable, black_gc, left_x, top_y,
right_x + 1, top_y);
if (bot_p && hwidth > 1)
XDrawLine (dpy, drawable, black_gc, left_x, bottom_y,
right_x + 1, bottom_y);
if (left_p && vwidth > 1)
XDrawLine (dpy, drawable, black_gc, left_x, top_y,
left_x, bottom_y + 1);
if (right_p && vwidth > 1)
XDrawLine (dpy, drawable, black_gc, right_x, top_y,
right_x, bottom_y + 1);
}
x_reset_clip_rectangles (f, gc);
/* Erase corners. */
if (hwidth > 1 && vwidth > 1)
{
if (left_p && top_p && x_inside_rect_p (clip_rect, 1,
left_x, top_y))
x_clear_rectangle (f, normal_gc, left_x, top_y, 1, 1, false);
if (left_p && bot_p && x_inside_rect_p (clip_rect, 1,
left_x, bottom_y))
x_clear_rectangle (f, normal_gc, left_x, bottom_y, 1, 1, false);
if (right_p && top_p && x_inside_rect_p (clip_rect, 1,
right_x, top_y))
x_clear_rectangle (f, normal_gc, right_x, top_y, 1, 1, false);
if (right_p && bot_p && x_inside_rect_p (clip_rect, 1,
right_x, bottom_y))
x_clear_rectangle (f, normal_gc, right_x, bottom_y, 1, 1, false);
}
x_reset_clip_rectangles (f, white_gc);
x_reset_clip_rectangles (f, black_gc);
#endif
}