From 2f983c178f9d2fffb5c6fdc639e89106ec0b66bf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 23 Sep 2025 08:13:37 +0530 Subject: [PATCH] Use the new path fill for spinner() --- kitty/decorations.c | 103 ++++++++------------------------------------ 1 file changed, 19 insertions(+), 84 deletions(-) diff --git a/kitty/decorations.c b/kitty/decorations.c index 378e00b7f..6c8f0649c 100644 --- a/kitty/decorations.c +++ b/kitty/decorations.c @@ -708,13 +708,6 @@ filled_D(Canvas *self, bool left) { else mirror_horizontally(fill_region(self, false)); } -static double -distance(double x1, double y1, double x2, double y2) { - const double dx = x1 - x2; - const double dy = y1 - y2; - return sqrt(dx * dx + dy * dy); -} - typedef double(*curve_func)(const void *, double t); #define NAME position_set @@ -727,27 +720,6 @@ static bool cmpr_point(Point, Point); static uint64_t hash_point(Point p) { return vt_hash_integer(p.val); } static bool cmpr_point(Point a, Point b) { return a.val == b.val; } -#define draw_parametrized_thin_curve(self, line_width, xfunc, yfunc, x_offset, y_offset) { \ - uint th = (uint)ceil(line_width); \ - div_t d = div(th, 2u); \ - int delta = d.quot, extra = d.rem; \ - uint num_samples = self->height * 8; \ - position_set seen; vt_init(&seen); \ - for (uint i = 0; i < num_samples + 1; i++) { \ - double t = i / (double)num_samples; \ - Point p = {.x=(int32_t)xfunc, .y=(int32_t)yfunc}; \ - position_set_itr q = vt_get(&seen, p); \ - if (!vt_is_end(q)) continue; \ - if (vt_is_end(vt_insert(&seen, p))) fatal("Out of memory"); \ - p.x += x_offset; \ - for (int y = MAX(0, p.y - delta); y < MIN(p.y + delta + extra, (int)self->height); y++) { \ - uint offset = y * self->width, start = MAX(0, p.x - delta); \ - memset(self->mask + offset + start, 255, minus((uint)MIN(p.x + delta + extra, (int)self->width), start)); \ - } \ - } \ - vt_cleanup(&seen); \ -} - typedef struct ClipRect { uint left, top, x_end, y_end; } ClipRect; static void @@ -815,46 +787,6 @@ draw_parametrized_curve_with_derivative_and_antialiasing( } } -static void -draw_parametrized_curve_with_derivative( - Canvas *self, void *curve_data, double line_width, curve_func xfunc, curve_func yfunc, curve_func x_prime, curve_func y_prime -) { - if (line_width <= 2 * self->supersample_factor) { - // The old algorithm looks better for very thin lines - draw_parametrized_thin_curve(self, line_width, xfunc(curve_data, t), yfunc(curve_data, t), 0, 0); - return; - } - double larger_dim = fmax(self->height, self->width); - double step = 1.0 / larger_dim; - const double min_step = step / 100., max_step = step; - line_width = fmax(1., line_width); - const double half_thickness = line_width / 2.0; - const double distance_limit = half_thickness; - double t = 0; - while(true) { - double x = xfunc(curve_data, t), y = yfunc(curve_data, t); - for (double dy = -line_width; dy <= line_width; dy++) { - for (double dx = -line_width; dx <= line_width; dx++) { - double px = x + dx, py = y + dy; - double dist = distance(x, y, px, py); - int row = (int)py, col = (int)px; - if (dist > distance_limit || row >= (int)self->height || row < 0 || col >= (int)self->width || col < 0) continue; - const int offset = row * self->width + col; - double alpha = 1.0 - (dist / half_thickness); - uint8_t old_alpha = self->mask[offset]; - self->mask[offset] = (uint8_t)(alpha * 255 + (1 - alpha) * old_alpha); - } - } - if (t >= 1.0) break; - // Dynamically adjust step size based on curve's derivative - double dx = x_prime(curve_data, t), dy = y_prime(curve_data, t); - double d = sqrt(dx * dx + dy * dy); - step = 1.0 / fmax(1e-6, d); - step = fmax(min_step, fmin(step, max_step)); - t = fmin(t + step, 1.0); - } -} - static void rounded_separator(Canvas *self, uint level, bool left) { uint gap = thickness(self, level, true); @@ -905,9 +837,12 @@ static void spinner(Canvas *self, uint level, double start_degrees, double end_degrees) { double x = self->width / 2.0, y = self->height / 2.0; double line_width = thickness_as_float(self, level, true); - double radius = fmax(0, fmin(x, y) - line_width / 2.0); + double radius = fmax(0, fmin(x, y) - 1 - line_width / 2.0); Circle c = circle(x, y, radius, start_degrees, end_degrees); - draw_parametrized_curve_with_derivative(self, &c, line_width, circle_x, circle_y, circle_prime_x, circle_prime_y); + uint leftover = minus(self->height, 2*(uint)ceil(radius) + 1) / 2; + ClipRect cr = {.top=leftover, .y_end=self->height - leftover, .x_end=self->width}; + draw_parametrized_curve_with_derivative_and_antialiasing( + self, &c, line_width, circle_x, circle_y, circle_prime_x, circle_prime_y, 0, 0, &cr); } static void @@ -933,7 +868,7 @@ static void draw_fish_eye(Canvas *self, uint level UNUSED) { double x = self->width / 2., y = self->height / 2.; double radius = fmin(x, y); - uint leftover = minus(self->height, 2*(uint)ceil(radius)) / 2; + uint leftover = minus(self->height, 2*(uint)ceil(radius) + 1) / 2; double central_radius = (2./3.) * radius; fill_circle_of_radius(self, x, y, central_radius, 255); double line_width = fmax(1. * self->supersample_factor, (radius - central_radius) / 2.5); @@ -1698,19 +1633,19 @@ START_ALLOW_CASE_RANGE C(L'', progress_bar, MIDDLE, true); C(L'', progress_bar, RIGHT, true); - S(L'', spinner, 1, 235, 305); - S(L'', spinner, 1, 270, 390); - S(L'', spinner, 1, 315, 470); - S(L'', spinner, 1, 360, 540); - S(L'', spinner, 1, 80, 220); - S(L'', spinner, 1, 170, 270); - S(L'○', spinner, 0, 0, 360); - S(L'◜', spinner, 1, 180, 270); - S(L'◝', spinner, 1, 270, 360); - S(L'◞', spinner, 1, 360, 450); - S(L'◟', spinner, 1, 450, 540); - S(L'◠', spinner, 1, 180, 360); - S(L'◡', spinner, 1, 0, 180); + C(L'', spinner, 1, 235, 305); + C(L'', spinner, 1, 270, 390); + C(L'', spinner, 1, 315, 470); + C(L'', spinner, 1, 360, 540); + C(L'', spinner, 1, 80, 220); + C(L'', spinner, 1, 170, 270); + C(L'○', spinner, 0, 0, 360); + C(L'◜', spinner, 1, 180, 270); + C(L'◝', spinner, 1, 270, 360); + C(L'◞', spinner, 1, 360, 450); + C(L'◟', spinner, 1, 450, 540); + C(L'◠', spinner, 1, 180, 360); + C(L'◡', spinner, 1, 0, 180); S(L'●', fill_circle, 1.0, 0, false); S(L'◉', draw_fish_eye, 0);