diff options
| author | Po Lu | 2022-05-10 16:50:10 +0800 |
|---|---|---|
| committer | Po Lu | 2022-05-10 16:50:10 +0800 |
| commit | e8d643eb835e2883e12032a7f25e94a8a3335c87 (patch) | |
| tree | 965b7b907a805c25fcf04b05e3e8872f5239f590 /src | |
| parent | c7b48b61d08f0b6a08584080badc60fe62ba1db1 (diff) | |
| download | emacs-e8d643eb835e2883e12032a7f25e94a8a3335c87.tar.gz emacs-e8d643eb835e2883e12032a7f25e94a8a3335c87.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 212 |
1 files changed, 140 insertions, 72 deletions
diff --git a/src/xterm.c b/src/xterm.c index c22a901ff4c..3e5cd45b431 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -7390,20 +7390,62 @@ x_setup_relief_colors (struct glyph_string *s) | |||
| 7390 | } | 7390 | } |
| 7391 | } | 7391 | } |
| 7392 | 7392 | ||
| 7393 | #ifndef USE_CAIRO | ||
| 7394 | static void | ||
| 7395 | x_fill_triangle (struct frame *f, GC gc, XPoint point1, | ||
| 7396 | XPoint point2, XPoint point3) | ||
| 7397 | { | ||
| 7398 | XPoint abc[3]; | ||
| 7399 | |||
| 7400 | abc[0] = point1; | ||
| 7401 | abc[1] = point2; | ||
| 7402 | abc[2] = point3; | ||
| 7403 | |||
| 7404 | XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), | ||
| 7405 | gc, abc, 3, Convex, CoordModeOrigin); | ||
| 7406 | } | ||
| 7407 | |||
| 7408 | static XPoint | ||
| 7409 | x_make_point (int x, int y) | ||
| 7410 | { | ||
| 7411 | XPoint pt; | ||
| 7412 | |||
| 7413 | pt.x = x; | ||
| 7414 | pt.y = y; | ||
| 7415 | |||
| 7416 | return pt; | ||
| 7417 | } | ||
| 7418 | |||
| 7419 | static bool | ||
| 7420 | x_inside_rect_p (XRectangle *rects, int nrects, int x, int y) | ||
| 7421 | { | ||
| 7422 | int i; | ||
| 7423 | |||
| 7424 | for (i = 0; i < nrects; ++i) | ||
| 7425 | { | ||
| 7426 | if (x >= rects[i].x && y >= rects[i].y | ||
| 7427 | && x < rects[i].x + rects[i].width | ||
| 7428 | && y < rects[i].y + rects[i].height) | ||
| 7429 | return true; | ||
| 7430 | } | ||
| 7431 | |||
| 7432 | return false; | ||
| 7433 | } | ||
| 7434 | #endif | ||
| 7393 | 7435 | ||
| 7394 | /* Draw a relief on frame F inside the rectangle given by LEFT_X, | 7436 | /* Draw a relief on frame F inside the rectangle given by LEFT_X, |
| 7395 | TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief | 7437 | TOP_Y, RIGHT_X, and BOTTOM_Y. VWIDTH and HWIDTH are respectively |
| 7396 | to draw, it must be >= 0. RAISED_P means draw a raised | 7438 | the thickness of the vertical relief (left and right) and |
| 7397 | relief. LEFT_P means draw a relief on the left side of | 7439 | horizontal relief (top and bottom) to draw, it must be >= 0. |
| 7398 | the rectangle. RIGHT_P means draw a relief on the right | 7440 | RAISED_P means draw a raised relief. LEFT_P means draw a relief on |
| 7399 | side of the rectangle. CLIP_RECT is the clipping rectangle to use | 7441 | the left side of the rectangle. RIGHT_P means draw a relief on the |
| 7400 | when drawing. */ | 7442 | right side of the rectangle. CLIP_RECT is the clipping rectangle |
| 7443 | to use when drawing. */ | ||
| 7401 | 7444 | ||
| 7402 | static void | 7445 | static void |
| 7403 | x_draw_relief_rect (struct frame *f, | 7446 | x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x, |
| 7404 | int left_x, int top_y, int right_x, int bottom_y, | 7447 | int bottom_y, int hwidth, int vwidth, bool raised_p, |
| 7405 | int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p, | 7448 | bool top_p, bool bot_p, bool left_p, bool right_p, |
| 7406 | bool left_p, bool right_p, | ||
| 7407 | XRectangle *clip_rect) | 7449 | XRectangle *clip_rect) |
| 7408 | { | 7450 | { |
| 7409 | #ifdef USE_CAIRO | 7451 | #ifdef USE_CAIRO |
| @@ -7479,90 +7521,116 @@ x_draw_relief_rect (struct frame *f, | |||
| 7479 | x_reset_clip_rectangles (f, top_left_gc); | 7521 | x_reset_clip_rectangles (f, top_left_gc); |
| 7480 | x_reset_clip_rectangles (f, bottom_right_gc); | 7522 | x_reset_clip_rectangles (f, bottom_right_gc); |
| 7481 | #else | 7523 | #else |
| 7482 | Display *dpy = FRAME_X_DISPLAY (f); | 7524 | GC gc, white_gc, black_gc, normal_gc; |
| 7483 | Drawable drawable = FRAME_X_DRAWABLE (f); | 7525 | Drawable drawable; |
| 7484 | int i; | 7526 | Display *dpy; |
| 7485 | GC gc; | ||
| 7486 | |||
| 7487 | if (raised_p) | ||
| 7488 | gc = f->output_data.x->white_relief.gc; | ||
| 7489 | else | ||
| 7490 | gc = f->output_data.x->black_relief.gc; | ||
| 7491 | XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); | ||
| 7492 | 7527 | ||
| 7493 | /* This code is more complicated than it has to be, because of two | 7528 | /* This code is more complicated than it has to be, because of two |
| 7494 | minor hacks to make the boxes look nicer: (i) if width > 1, draw | 7529 | minor hacks to make the boxes look nicer: (i) if width > 1, draw |
| 7495 | the outermost line using the black relief. (ii) Omit the four | 7530 | the outermost line using the black relief. (ii) Omit the four |
| 7496 | corner pixels. */ | 7531 | corner pixels. */ |
| 7497 | 7532 | ||
| 7498 | /* Top. */ | 7533 | white_gc = f->output_data.x->white_relief.gc; |
| 7499 | if (top_p) | 7534 | black_gc = f->output_data.x->black_relief.gc; |
| 7500 | { | 7535 | normal_gc = f->output_data.x->normal_gc; |
| 7501 | if (hwidth == 1) | ||
| 7502 | XDrawLine (dpy, drawable, gc, | ||
| 7503 | left_x + left_p, top_y, | ||
| 7504 | right_x + !right_p, top_y); | ||
| 7505 | 7536 | ||
| 7506 | for (i = 1; i < hwidth; ++i) | 7537 | drawable = FRAME_X_DRAWABLE (f); |
| 7507 | XDrawLine (dpy, drawable, gc, | 7538 | dpy = FRAME_X_DISPLAY (f); |
| 7508 | left_x + i * left_p, top_y + i, | ||
| 7509 | right_x + 1 - i * right_p, top_y + i); | ||
| 7510 | } | ||
| 7511 | 7539 | ||
| 7512 | /* Left. */ | 7540 | x_set_clip_rectangles (f, white_gc, clip_rect, 1); |
| 7513 | if (left_p) | 7541 | x_set_clip_rectangles (f, black_gc, clip_rect, 1); |
| 7514 | { | ||
| 7515 | if (vwidth == 1) | ||
| 7516 | XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); | ||
| 7517 | 7542 | ||
| 7518 | for (i = 1; i < vwidth; ++i) | ||
| 7519 | XDrawLine (dpy, drawable, gc, | ||
| 7520 | left_x + i, top_y + (i + 1) * top_p, | ||
| 7521 | left_x + i, bottom_y + 1 - (i + 1) * bot_p); | ||
| 7522 | } | ||
| 7523 | |||
| 7524 | XSetClipMask (dpy, gc, None); | ||
| 7525 | if (raised_p) | 7543 | if (raised_p) |
| 7526 | gc = f->output_data.x->black_relief.gc; | 7544 | gc = white_gc; |
| 7527 | else | 7545 | else |
| 7528 | gc = f->output_data.x->white_relief.gc; | 7546 | gc = black_gc; |
| 7529 | XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); | ||
| 7530 | 7547 | ||
| 7531 | /* Outermost top line. */ | 7548 | /* Draw lines. */ |
| 7532 | if (top_p && hwidth > 1) | ||
| 7533 | XDrawLine (dpy, drawable, gc, | ||
| 7534 | left_x + left_p, top_y, | ||
| 7535 | right_x + !right_p, top_y); | ||
| 7536 | 7549 | ||
| 7537 | /* Outermost left line. */ | 7550 | if (top_p) |
| 7538 | if (left_p && vwidth > 1) | 7551 | x_fill_rectangle (f, gc, left_x, top_y, |
| 7539 | XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); | 7552 | right_x - left_x + 1, hwidth, |
| 7553 | false); | ||
| 7554 | |||
| 7555 | if (left_p) | ||
| 7556 | x_fill_rectangle (f, gc, left_x, top_y, vwidth, | ||
| 7557 | bottom_y - top_y + 1, false); | ||
| 7558 | |||
| 7559 | if (raised_p) | ||
| 7560 | gc = black_gc; | ||
| 7561 | else | ||
| 7562 | gc = white_gc; | ||
| 7540 | 7563 | ||
| 7541 | /* Bottom. */ | ||
| 7542 | if (bot_p) | 7564 | if (bot_p) |
| 7565 | x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1, | ||
| 7566 | right_x - left_x + 1, hwidth, false); | ||
| 7567 | |||
| 7568 | if (right_p) | ||
| 7569 | x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y, | ||
| 7570 | vwidth, bottom_y - top_y + 1, false); | ||
| 7571 | |||
| 7572 | /* Draw corners. */ | ||
| 7573 | |||
| 7574 | if (bot_p && left_p) | ||
| 7575 | x_fill_triangle (f, raised_p ? white_gc : black_gc, | ||
| 7576 | x_make_point (left_x, bottom_y - hwidth), | ||
| 7577 | x_make_point (left_x + vwidth, bottom_y - hwidth), | ||
| 7578 | x_make_point (left_x, bottom_y)); | ||
| 7579 | |||
| 7580 | if (top_p && right_p) | ||
| 7581 | x_fill_triangle (f, raised_p ? white_gc : black_gc, | ||
| 7582 | x_make_point (right_x - vwidth, top_y), | ||
| 7583 | x_make_point (right_x, top_y), | ||
| 7584 | x_make_point (right_x - vwidth, top_y + hwidth)); | ||
| 7585 | |||
| 7586 | /* Draw outer line. */ | ||
| 7587 | |||
| 7588 | if (top_p && left_p && bot_p && right_p | ||
| 7589 | && hwidth > 1 && vwidth > 1) | ||
| 7590 | x_draw_rectangle (f, black_gc, left_x, top_y, | ||
| 7591 | right_x - left_x, top_y - bottom_y); | ||
| 7592 | else | ||
| 7543 | { | 7593 | { |
| 7544 | if (hwidth >= 1) | 7594 | if (top_p && hwidth > 1) |
| 7545 | XDrawLine (dpy, drawable, gc, | 7595 | XDrawLine (dpy, drawable, black_gc, left_x, top_y, |
| 7546 | left_x + left_p, bottom_y, | 7596 | right_x + 1, top_y); |
| 7547 | right_x + !right_p, bottom_y); | 7597 | |
| 7598 | if (bot_p && hwidth > 1) | ||
| 7599 | XDrawLine (dpy, drawable, black_gc, left_x, bottom_y, | ||
| 7600 | right_x + 1, bottom_y); | ||
| 7601 | |||
| 7602 | if (left_p && vwidth > 1) | ||
| 7603 | XDrawLine (dpy, drawable, black_gc, left_x, top_y, | ||
| 7604 | left_x, bottom_y + 1); | ||
| 7548 | 7605 | ||
| 7549 | for (i = 1; i < hwidth; ++i) | 7606 | if (right_p && vwidth > 1) |
| 7550 | XDrawLine (dpy, drawable, gc, | 7607 | XDrawLine (dpy, drawable, black_gc, right_x, top_y, |
| 7551 | left_x + i * left_p, bottom_y - i, | 7608 | right_x, bottom_y + 1); |
| 7552 | right_x + 1 - i * right_p, bottom_y - i); | ||
| 7553 | } | 7609 | } |
| 7554 | 7610 | ||
| 7555 | /* Right. */ | 7611 | /* Erase corners. */ |
| 7556 | if (right_p) | 7612 | |
| 7613 | if (hwidth > 1 && vwidth > 1) | ||
| 7557 | { | 7614 | { |
| 7558 | for (i = 0; i < vwidth; ++i) | 7615 | if (left_p && top_p && x_inside_rect_p (clip_rect, 1, |
| 7559 | XDrawLine (dpy, drawable, gc, | 7616 | left_x, top_y)) |
| 7560 | right_x - i, top_y + (i + 1) * top_p, | 7617 | x_clear_rectangle (f, normal_gc, left_x, top_y, 1, 1, false); |
| 7561 | right_x - i, bottom_y + 1 - (i + 1) * bot_p); | ||
| 7562 | } | ||
| 7563 | 7618 | ||
| 7564 | x_reset_clip_rectangles (f, gc); | 7619 | if (left_p && bot_p && x_inside_rect_p (clip_rect, 1, |
| 7620 | left_x, bottom_y)) | ||
| 7621 | x_clear_rectangle (f, normal_gc, left_x, bottom_y, 1, 1, false); | ||
| 7622 | |||
| 7623 | if (right_p && top_p && x_inside_rect_p (clip_rect, 1, | ||
| 7624 | right_x, top_y)) | ||
| 7625 | x_clear_rectangle (f, normal_gc, right_x, top_y, 1, 1, false); | ||
| 7626 | |||
| 7627 | if (right_p && bot_p && x_inside_rect_p (clip_rect, 1, | ||
| 7628 | right_x, bottom_y)) | ||
| 7629 | x_clear_rectangle (f, normal_gc, right_x, bottom_y, 1, 1, false); | ||
| 7630 | } | ||
| 7565 | 7631 | ||
| 7632 | x_reset_clip_rectangles (f, white_gc); | ||
| 7633 | x_reset_clip_rectangles (f, black_gc); | ||
| 7566 | #endif | 7634 | #endif |
| 7567 | } | 7635 | } |
| 7568 | 7636 | ||