emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master e8d643eb83: Fix X11 relief background clearning when hwidth is la


From: Po Lu
Subject: master e8d643eb83: Fix X11 relief background clearning when hwidth is larger than vwidth
Date: Tue, 10 May 2022 04:50:35 -0400 (EDT)

branch: master
commit e8d643eb835e2883e12032a7f25e94a8a3335c87
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 src/xterm.c | 212 +++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 140 insertions(+), 72 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index c22a901ff4..3e5cd45b43 100644
--- a/src/xterm.c
+++ b/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)
+    x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
+                     right_x - left_x + 1, hwidth, false);
+
+  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
     {
-      if (hwidth >= 1)
-        XDrawLine (dpy, drawable, gc,
-                  left_x + left_p, bottom_y,
-                  right_x + !right_p, bottom_y);
+      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);
 
-      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);
+      if (right_p && vwidth > 1)
+       XDrawLine (dpy, drawable, black_gc, right_x, top_y,
+                  right_x, bottom_y + 1);
     }
 
-  /* Right.  */
-  if (right_p)
+  /* Erase corners.  */
+
+  if (hwidth > 1 && vwidth > 1)
     {
-      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 (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);
 
-  x_reset_clip_rectangles (f, gc);
+      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
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]