URI: 
       Remove unneeded clipping code - ltk - GUI toolkit for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
  HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit d0faf9b6f4464428cac5de55e56cd1a0a92b45ef
   DIR parent d0a001aaf611434b7abb0ca173e9bcf1fae73983
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Fri,  3 May 2024 23:28:52 +0200
       
       Remove unneeded clipping code
       
       Diffstat:
         M src/ltk/button.c                    |       2 +-
         M src/ltk/checkbutton.c               |       2 +-
         M src/ltk/entry.c                     |       2 +-
         M src/ltk/graphics.h                  |       2 +-
         M src/ltk/graphics_xlib.c             |     168 ++-----------------------------
         M src/ltk/menu.c                      |       4 ++--
       
       6 files changed, 17 insertions(+), 163 deletions(-)
       ---
   DIR diff --git a/src/ltk/button.c b/src/ltk/button.c
       @@ -140,7 +140,7 @@ ltk_button_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect
                /* FIXME: support theme setting for border sides */
                if (bw > 0) {
                        ltk_surface_draw_border_clipped(
       -                        draw_surf, border, draw_rect, draw_clip, bw, LTK_BORDER_ALL
       +                        draw_surf, border, draw_rect, bw, LTK_BORDER_ALL, draw_clip
                        );
                }
                int text_w, text_h;
   DIR diff --git a/src/ltk/checkbutton.c b/src/ltk/checkbutton.c
       @@ -189,7 +189,7 @@ ltk_checkbutton_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk
                ltk_surface_fill_rect(draw_surf, box_fill, box_clip);
                if (box_bw > 0) {
                        ltk_surface_draw_border_clipped(
       -                        draw_surf, box_border, box_rect, box_clip, box_bw, LTK_BORDER_ALL
       +                        draw_surf, box_border, box_rect, box_bw, LTK_BORDER_ALL, box_clip
                        );
                }
                int text_w, text_h;
   DIR diff --git a/src/ltk/entry.c b/src/ltk/entry.c
       @@ -237,7 +237,7 @@ ltk_entry_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect 
                ltk_surface_fill_rect(draw_surf, fill, draw_clip);
                if (bw > 0) {
                        ltk_surface_draw_border_clipped(
       -                        draw_surf, border, draw_rect, draw_clip, bw, LTK_BORDER_ALL
       +                        draw_surf, border, draw_rect, bw, LTK_BORDER_ALL, draw_clip
                        );
                }
        
   DIR diff --git a/src/ltk/graphics.h b/src/ltk/graphics.h
       @@ -59,7 +59,7 @@ void ltk_surface_draw_rect(ltk_surface *s, ltk_color *c, ltk_rect rect, int line
        void ltk_surface_fill_rect(ltk_surface *s, ltk_color *c, ltk_rect rect);
        /* FIXME: document properly, especially difference to draw_rect with offsets and line_width */
        void ltk_surface_draw_border(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width, ltk_border_sides border_sides);
       -void ltk_surface_draw_border_clipped(ltk_surface *s, ltk_color *c, ltk_rect rect, ltk_rect clip_rect, int line_width, ltk_border_sides border_sides);
       +void ltk_surface_draw_border_clipped(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width, ltk_border_sides border_sides, ltk_rect clip);
        void ltk_surface_fill_polygon(ltk_surface *s, ltk_color *c, ltk_point *points, size_t npoints);
        void ltk_surface_fill_polygon_clipped(ltk_surface *s, ltk_color *c, ltk_point *points, size_t npoints, ltk_rect clip);
        void ltk_surface_fill_ellipse(ltk_surface *s, ltk_color *c, ltk_rect rect);
   DIR diff --git a/src/ltk/graphics_xlib.c b/src/ltk/graphics_xlib.c
       @@ -135,48 +135,14 @@ ltk_surface_draw_border(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_wi
        }
        
        void
       -ltk_surface_draw_border_clipped(ltk_surface *s, ltk_color *c, ltk_rect rect, ltk_rect clip_rect, int line_width, ltk_border_sides border_sides) {
       +ltk_surface_draw_border_clipped(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width, ltk_border_sides border_sides, ltk_rect clip) {
                if (line_width <= 0)
                        return;
       -        XSetForeground(s->window->renderdata->dpy, s->window->gc, c->xcolor.pixel);
       -        int width;
       -        ltk_rect final_rect = ltk_rect_intersect(rect, clip_rect);
       -        if (final_rect.w == 0 || final_rect.h == 0)
       -                return;
       -        /* TODO: I guess this could be done with fewer branches because it isn't really necessary to perform
       -           a completel rect intersection each time, but it probably doesn't matter. */
       -        if (border_sides & LTK_BORDER_TOP) {
       -                width = rect.y - final_rect.y;
       -                if (width > -line_width) {
       -                        width = line_width + width;
       -                        ltk_rect draw_rect = ltk_rect_intersect(final_rect, (ltk_rect){final_rect.x, final_rect.y, final_rect.w, width});
       -                        XFillRectangle(s->window->renderdata->dpy, s->d, s->window->gc, draw_rect.x, draw_rect.y, draw_rect.w, draw_rect.h);
       -                }
       -        }
       -        if (border_sides & LTK_BORDER_BOTTOM) {
       -                width = (final_rect.y + final_rect.h) - (rect.y + rect.h);
       -                if (width > -line_width) {
       -                        width = line_width + width;
       -                        ltk_rect draw_rect = ltk_rect_intersect(final_rect, (ltk_rect){final_rect.x, final_rect.y + final_rect.h - width, final_rect.w, width});
       -                        XFillRectangle(s->window->renderdata->dpy, s->d, s->window->gc, draw_rect.x, draw_rect.y, draw_rect.w, draw_rect.h);
       -                }
       -        }
       -        if (border_sides & LTK_BORDER_LEFT) {
       -                width = rect.x - final_rect.x;
       -                if (width > -line_width) {
       -                        width = line_width + width;
       -                        ltk_rect draw_rect = ltk_rect_intersect(final_rect, (ltk_rect){final_rect.x, final_rect.y, width, final_rect.h});
       -                        XFillRectangle(s->window->renderdata->dpy, s->d, s->window->gc, draw_rect.x, draw_rect.y, draw_rect.w, draw_rect.h);
       -                }
       -        }
       -        if (border_sides & LTK_BORDER_RIGHT) {
       -                width = (final_rect.x + final_rect.w) - (rect.x + rect.w);
       -                if (width > -line_width) {
       -                        width = line_width + width;
       -                        ltk_rect draw_rect = ltk_rect_intersect(final_rect, (ltk_rect){final_rect.x + final_rect.w - width, final_rect.y, width, final_rect.h});
       -                        XFillRectangle(s->window->renderdata->dpy, s->d, s->window->gc, draw_rect.x, draw_rect.y, draw_rect.w, draw_rect.h);
       -                }
       -        }
       +        /* NOTE: XRectangle only uses short, so this could cause issues */
       +        XRectangle xclip = {clip.x, clip.y, clip.w, clip.h};
       +        XSetClipRectangles(s->window->renderdata->dpy, s->window->gc, 0, 0, &xclip, 1, Unsorted);
       +        ltk_surface_draw_border(s, c, rect, line_width, border_sides);
       +        XSetClipMask(s->window->renderdata->dpy, s->window->gc, None);
        }
        
        void
       @@ -207,125 +173,13 @@ ltk_surface_fill_polygon(ltk_surface *s, ltk_color *c, ltk_point *points, size_t
                        ltk_free(final_points);
        }
        
       -static inline void
       -swap_ptr(void **ptr1, void **ptr2) {
       -        void *tmp = *ptr1;
       -        *ptr1 = *ptr2;
       -        *ptr2 = tmp;
       -}
       -
       -#define check_size(cond) if (!(cond)) ltk_fatal("Unable to perform polygon clipping. This is a bug, tell lumidify about it.\n")
       -
       -/* FIXME: xlib already includes clipping... */
       -/* FIXME: this can probably be optimized */
       -/* This is basically Sutherland-Hodgman, but only the special case for clipping rectangles. */
        void
        ltk_surface_fill_polygon_clipped(ltk_surface *s, ltk_color *c, ltk_point *points, size_t npoints, ltk_rect clip) {
       -        /* FIXME: is this even more efficient? */
       -        XPoint tmp_points1[12]; /* to avoid extra allocations when not necessary */
       -        XPoint tmp_points2[12];
       -        XPoint *points1;
       -        XPoint *points2;
       -        /* FIXME: be a bit smarter about this */
       -        if (npoints <= 6) {
       -                points1 = tmp_points1;
       -                points2 = tmp_points2;
       -        } else {
       -                /* FIXME: I'm pretty sure there can never be more points than this
       -                   since we're only clipping against a rectangle, right?
       -                   If I can be sure about that, I can remove all the check_size's below. */
       -                points1 = ltk_reallocarray(NULL, npoints, sizeof(XPoint) * 2);
       -                points2 = ltk_reallocarray(NULL, npoints, sizeof(XPoint) * 2);
       -        }
       -
       -        size_t num1 = npoints;
       -        size_t num2 = 0;
       -        for (size_t i = 0; i < npoints; i++) {
       -                points1[i].x = (short)points[i].x;
       -                points1[i].y = (short)points[i].y;
       -        }
       -
       -        for (size_t i = 0; i < num1; i++) {
       -                XPoint p1 = points1[i];
       -                XPoint p2 = points1[(i + 1) % num1];
       -                if (p1.x >= clip.x) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = p1;
       -                        if (p2.x < clip.x) {
       -                                check_size(num2 < npoints * 2);
       -                                points2[num2++] = (XPoint){.x = (short)clip.x, .y = (short)(p1.y + (p2.y - p1.y) * (float)(clip.x - p1.x) / (p2.x - p1.x))};
       -                        }
       -                } else if (p2.x >= clip.x) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = (XPoint){.x = (short)clip.x, .y = (short)(p1.y + (p2.y - p1.y) * (float)(clip.x - p1.x) / (p2.x - p1.x))};
       -                }
       -        }
       -        num1 = num2;
       -        num2 = 0;
       -        swap_ptr((void**)&points1, (void**)&points2);
       -
       -        for (size_t i = 0; i < num1; i++) {
       -                XPoint p1 = points1[i];
       -                XPoint p2 = points1[(i + 1) % num1];
       -                if (p1.x <= clip.x + clip.w) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = p1;
       -                        if (p2.x > clip.x + clip.w) {
       -                                check_size(num2 < npoints * 2);
       -                                points2[num2++] = (XPoint){.x = (short)(clip.x + clip.w), .y = (short)(p1.y + (p2.y - p1.y) * (float)(clip.x + clip.w - p1.x) / (p2.x - p1.x))};
       -                        }
       -                } else if (p2.x <= clip.x + clip.w) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = (XPoint){.x = (short)(clip.x + clip.w), .y = (short)(p1.y + (p2.y - p1.y) * (float)(clip.x + clip.w - p1.x) / (p2.x - p1.x))};
       -                }
       -        }
       -        num1 = num2;
       -        num2 = 0;
       -        swap_ptr((void**)&points1, (void**)&points2);
       -
       -        for (size_t i = 0; i < num1; i++) {
       -                XPoint p1 = points1[i];
       -                XPoint p2 = points1[(i + 1) % num1];
       -                if (p1.y >= clip.y) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = p1;
       -                        if (p2.y < clip.y) {
       -                                check_size(num2 < npoints * 2);
       -                                points2[num2++] = (XPoint){.y = (short)clip.y, .x = (short)(p1.x + (p2.x - p1.x) * (float)(clip.y - p1.y) / (p2.y - p1.y))};
       -                        }
       -                } else if (p2.y >= clip.y) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = (XPoint){.y = (short)clip.y, .x = (short)(p1.x + (p2.x - p1.x) * (float)(clip.y - p1.y) / (p2.y - p1.y))};
       -                }
       -        }
       -        num1 = num2;
       -        num2 = 0;
       -        swap_ptr((void**)&points1, (void**)&points2);
       -
       -        for (size_t i = 0; i < num1; i++) {
       -                XPoint p1 = points1[i];
       -                XPoint p2 = points1[(i + 1) % num1];
       -                if (p1.y <= clip.y + clip.h) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = p1;
       -                        if (p2.y > clip.y + clip.h) {
       -                                check_size(num2 < npoints * 2);
       -                                points2[num2++] = (XPoint){.y = (short)clip.y + clip.h, .x = (short)(p1.x + (p2.x - p1.x) * (float)(clip.y + clip.h - p1.y) / (p2.y - p1.y))};
       -                        }
       -                } else if (p2.y <= clip.y + clip.h) {
       -                        check_size(num2 < npoints * 2);
       -                        points2[num2++] = (XPoint){.y = (short)clip.y + clip.h, .x = (short)(p1.x + (p2.x - p1.x) * (float)(clip.y + clip.h - p1.y) / (p2.y - p1.y))};
       -                }
       -        }
       -
       -        if (num2 > 0) {
       -                XSetForeground(s->window->renderdata->dpy, s->window->gc, c->xcolor.pixel);
       -                XFillPolygon(s->window->renderdata->dpy, s->d, s->window->gc, points2, (int)num2, Complex, CoordModeOrigin);
       -        }
       -        if (npoints > 6) {
       -                ltk_free(points1);
       -                ltk_free(points2);
       -        }
       +        /* NOTE: XRectangle only uses short, so this could cause issues */
       +        XRectangle xclip = {clip.x, clip.y, clip.w, clip.h};
       +        XSetClipRectangles(s->window->renderdata->dpy, s->window->gc, 0, 0, &xclip, 1, Unsorted);
       +        ltk_surface_fill_polygon(s, c, points, npoints);
       +        XSetClipMask(s->window->renderdata->dpy, s->window->gc, None);
        }
        
        void
   DIR diff --git a/src/ltk/menu.c b/src/ltk/menu.c
       @@ -373,7 +373,7 @@ ltk_menuentry_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_r
                        };
                        ltk_surface_fill_polygon_clipped(draw_surf, text, arrow_points, LENGTH(arrow_points), surf_clip);
                }
       -        ltk_surface_draw_border_clipped(draw_surf, border, (ltk_rect){x, y, lrect.w, lrect.h}, surf_clip, bw, t->border_sides);
       +        ltk_surface_draw_border_clipped(draw_surf, border, (ltk_rect){x, y, lrect.w, lrect.h}, bw, t->border_sides, surf_clip);
                self->dirty = 0;
        }
        
       @@ -447,7 +447,7 @@ ltk_menu_draw(ltk_widget *self, ltk_surface *s, int x, int y, ltk_rect clip) {
                        arrow_points[2] = (ltk_point){wx + ww / 2 + arrow_size / 2, wy + wh - arrow_pad - mbw - arrow_size};
                        ltk_surface_fill_polygon(s, t->scroll_arrow_color, arrow_points, 3);
                }
       -        ltk_surface_draw_border_clipped(s, t->border, (ltk_rect){x, y, lrect.w, lrect.h}, surf_clip, mbw, LTK_BORDER_ALL);
       +        ltk_surface_draw_border_clipped(s, t->border, (ltk_rect){x, y, lrect.w, lrect.h}, mbw, LTK_BORDER_ALL, surf_clip);
        
                self->dirty = 0;
        }