Skip to content

Commit 89b1c35

Browse files
committed
Implement clipping regions for filling path
1 parent c911f79 commit 89b1c35

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

kitty/decorations.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -314,26 +314,41 @@ add_vholes(Canvas *self, uint level, uint num) {
314314
}
315315
}
316316

317+
static Range
318+
hline_limits(Canvas *self, uint y, uint level) {
319+
uint sz = thickness(self, level, false);
320+
Range r = {.start=minus(y, sz / 2)};
321+
r.end = min(r.start + sz, self->height);
322+
return r;
323+
}
317324

318325
static void
319326
draw_hline(Canvas *self, uint x1, uint x2, uint y, uint level) {
320327
// Draw a horizontal line between [x1, x2) centered at y with the thickness given by level and self->supersample_factor
321-
uint sz = thickness(self, level, false);
322-
uint start = minus(y, sz / 2);
323-
for (uint y = start; y < min(start + sz, self->height); y++) {
328+
Range r = hline_limits(self, y, level);
329+
for (uint y = r.start; y < r.end; y++) {
324330
uint8_t *py = self->mask + y * self->width;
325331
memset(py + x1, 255, minus(min(x2, self->width), x1));
326332
}
327333
}
328334

335+
static Range
336+
vline_limits(Canvas *self, uint x, uint level) {
337+
uint sz = thickness(self, level, true);
338+
Range r = {.start = minus(x, sz / 2)};
339+
r.end = min(r.start + sz, self->width);
340+
return r;
341+
}
342+
343+
329344
static void
330345
draw_vline(Canvas *self, uint y1, uint y2, uint x, uint level) {
331346
// Draw a vertical line between [y1, y2) centered at x with the thickness given by level and self->supersample_factor
332-
uint sz = thickness(self, level, true);
333-
uint start = minus(x, sz / 2), end = min(start + sz, self->width), xsz = minus(end, start);
347+
Range r = vline_limits(self, x, level);
348+
uint xsz = minus(r.end, r.start);
334349
for (uint y = y1; y < min(y2, self->height); y++) {
335350
uint8_t *py = self->mask + y * self->width;
336-
memset(py + start, 255, xsz);
351+
memset(py + r.start, 255, xsz);
337352
}
338353
}
339354

@@ -733,10 +748,12 @@ static bool cmpr_point(Point a, Point b) { return a.val == b.val; }
733748
vt_cleanup(&seen); \
734749
}
735750

751+
typedef struct ClipRect { uint left, top, width, height; } ClipRect;
752+
736753
static void
737754
draw_parametrized_curve_with_derivative_and_antialiasing(
738755
Canvas *self, void *curve_data, double line_width, curve_func xfunc, curve_func yfunc,
739-
curve_func x_prime, curve_func y_prime, double x_offset, double y_offset
756+
curve_func x_prime, curve_func y_prime, double x_offset, double y_offset, const ClipRect *clip_to
740757
) {
741758
line_width = fmax(1., line_width);
742759
double half_thickness = line_width / 2.0;
@@ -747,6 +764,7 @@ draw_parametrized_curve_with_derivative_and_antialiasing(
747764
const double min_step = step / 1000., max_step = step;
748765
RAII_ALLOC(FloatPoint, samples, malloc(sizeof(FloatPoint) * cap));
749766
if (!samples) fatal("Out of memory");
767+
ClipRect cr = clip_to ? *clip_to : (ClipRect){.width=self->width, .height=self->height};
750768
while (true) {
751769
samples[i] = (FloatPoint){xfunc(curve_data, t) + x_offset, yfunc(curve_data, t) + y_offset};
752770
if (t >= 1.0) break;
@@ -764,9 +782,9 @@ draw_parametrized_curve_with_derivative_and_antialiasing(
764782
}
765783
}
766784
const uint num_samples = i;
767-
for (uint py = 0; py < self->height; py++) {
785+
for (uint py = cr.top; py < cr.height; py++) {
768786
uint ypos = self->width * py;
769-
for (uint px = 0; px < self->width; px++) {
787+
for (uint px = cr.left; px < cr.width; px++) {
770788
// Center of the current pixel
771789
double pixel_center_x = (double)px + 0.5;
772790
double pixel_center_y = (double)py + 0.5;
@@ -1408,8 +1426,13 @@ rounded_corner(Canvas *self, uint level, Corner which) {
14081426
uint cell_height_is_odd = (self->height / self->supersample_factor) & 1;
14091427
// adjust for odd cell dimensions to line up with box drawing lines
14101428
double x_offset = cell_width_is_odd ? 0 : 0.5, y_offset = cell_height_is_odd ? 0 : 0.5;
1429+
ClipRect cr = {.width=self->width, .height=self->height};
1430+
if (which & TOP_EDGE) cr.top = hline_limits(self, half_height(self), level).start;
1431+
else cr.height = hline_limits(self, half_height(self), level).end;
1432+
if (which & LEFT_EDGE) cr.left = vline_limits(self, half_width(self), level).start;
1433+
else cr.width = vline_limits(self, half_width(self), level).end;
14111434
draw_parametrized_curve_with_derivative_and_antialiasing(
1412-
self, &r, line_width, rectircle_x, rectircle_y, rectircle_x_prime, rectircle_y_prime, x_offset, y_offset);
1435+
self, &r, line_width, rectircle_x, rectircle_y, rectircle_x_prime, rectircle_y_prime, x_offset, y_offset, &cr);
14131436
// make the vertical stems be same brightness as straightline segments
14141437
if (which & TOP_EDGE) fractional_vline(self, level, self->height - self->width / 2, self->height);
14151438
else fractional_vline(self, level, 0, self->width / 2);

0 commit comments

Comments
 (0)