ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | LICENSE

commit d0faf9b6f4464428cac5de55e56cd1a0a92b45ef
parent d0a001aaf611434b7abb0ca173e9bcf1fae73983
Author: lumidify <nobody@lumidify.org>
Date:   Fri,  3 May 2024 23:28:52 +0200

Remove unneeded clipping code

Diffstat:
Msrc/ltk/button.c | 2+-
Msrc/ltk/checkbutton.c | 2+-
Msrc/ltk/entry.c | 2+-
Msrc/ltk/graphics.h | 2+-
Msrc/ltk/graphics_xlib.c | 168++++++-------------------------------------------------------------------------
Msrc/ltk/menu.c | 4++--
6 files changed, 17 insertions(+), 163 deletions(-)

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; 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; 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 ); } 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); 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 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; }