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:
parent
c7b48b61d0
commit
e8d643eb83
1 changed files with 141 additions and 73 deletions
214
src/xterm.c
214
src/xterm.c
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue