commit d0faf9b6f4464428cac5de55e56cd1a0a92b45ef
parent d0a001aaf611434b7abb0ca173e9bcf1fae73983
Author: lumidify <nobody@lumidify.org>
Date: Fri, 3 May 2024 23:28:52 +0200
Remove unneeded clipping code
Diffstat:
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;
}