@@ -708,13 +708,6 @@ filled_D(Canvas *self, bool left) {
708708 else mirror_horizontally (fill_region (self , false));
709709}
710710
711- static double
712- distance (double x1 , double y1 , double x2 , double y2 ) {
713- const double dx = x1 - x2 ;
714- const double dy = y1 - y2 ;
715- return sqrt (dx * dx + dy * dy );
716- }
717-
718711typedef double (* curve_func )(const void * , double t );
719712
720713#define NAME position_set
@@ -727,27 +720,6 @@ static bool cmpr_point(Point, Point);
727720static uint64_t hash_point (Point p ) { return vt_hash_integer (p .val ); }
728721static bool cmpr_point (Point a , Point b ) { return a .val == b .val ; }
729722
730- #define draw_parametrized_thin_curve (self , line_width , xfunc , yfunc , x_offset , y_offset ) { \
731- uint th = (uint)ceil(line_width); \
732- div_t d = div(th, 2u); \
733- int delta = d.quot, extra = d.rem; \
734- uint num_samples = self->height * 8; \
735- position_set seen; vt_init(&seen); \
736- for (uint i = 0; i < num_samples + 1; i++) { \
737- double t = i / (double)num_samples; \
738- Point p = {.x=(int32_t)xfunc, .y=(int32_t)yfunc}; \
739- position_set_itr q = vt_get(&seen, p); \
740- if (!vt_is_end(q)) continue; \
741- if (vt_is_end(vt_insert(&seen, p))) fatal("Out of memory"); \
742- p.x += x_offset; \
743- for (int y = MAX(0, p.y - delta); y < MIN(p.y + delta + extra, (int)self->height); y++) { \
744- uint offset = y * self->width, start = MAX(0, p.x - delta); \
745- memset(self->mask + offset + start, 255, minus((uint)MIN(p.x + delta + extra, (int)self->width), start)); \
746- } \
747- } \
748- vt_cleanup(&seen); \
749- }
750-
751723typedef struct ClipRect { uint left , top , x_end , y_end ; } ClipRect ;
752724
753725static void
@@ -815,46 +787,6 @@ draw_parametrized_curve_with_derivative_and_antialiasing(
815787 }
816788}
817789
818- static void
819- draw_parametrized_curve_with_derivative (
820- Canvas * self , void * curve_data , double line_width , curve_func xfunc , curve_func yfunc , curve_func x_prime , curve_func y_prime
821- ) {
822- if (line_width <= 2 * self -> supersample_factor ) {
823- // The old algorithm looks better for very thin lines
824- draw_parametrized_thin_curve (self , line_width , xfunc (curve_data , t ), yfunc (curve_data , t ), 0 , 0 );
825- return ;
826- }
827- double larger_dim = fmax (self -> height , self -> width );
828- double step = 1.0 / larger_dim ;
829- const double min_step = step / 100. , max_step = step ;
830- line_width = fmax (1. , line_width );
831- const double half_thickness = line_width / 2.0 ;
832- const double distance_limit = half_thickness ;
833- double t = 0 ;
834- while (true) {
835- double x = xfunc (curve_data , t ), y = yfunc (curve_data , t );
836- for (double dy = - line_width ; dy <= line_width ; dy ++ ) {
837- for (double dx = - line_width ; dx <= line_width ; dx ++ ) {
838- double px = x + dx , py = y + dy ;
839- double dist = distance (x , y , px , py );
840- int row = (int )py , col = (int )px ;
841- if (dist > distance_limit || row >= (int )self -> height || row < 0 || col >= (int )self -> width || col < 0 ) continue ;
842- const int offset = row * self -> width + col ;
843- double alpha = 1.0 - (dist / half_thickness );
844- uint8_t old_alpha = self -> mask [offset ];
845- self -> mask [offset ] = (uint8_t )(alpha * 255 + (1 - alpha ) * old_alpha );
846- }
847- }
848- if (t >= 1.0 ) break ;
849- // Dynamically adjust step size based on curve's derivative
850- double dx = x_prime (curve_data , t ), dy = y_prime (curve_data , t );
851- double d = sqrt (dx * dx + dy * dy );
852- step = 1.0 / fmax (1e-6 , d );
853- step = fmax (min_step , fmin (step , max_step ));
854- t = fmin (t + step , 1.0 );
855- }
856- }
857-
858790static void
859791rounded_separator (Canvas * self , uint level , bool left ) {
860792 uint gap = thickness (self , level , true);
@@ -905,9 +837,12 @@ static void
905837spinner (Canvas * self , uint level , double start_degrees , double end_degrees ) {
906838 double x = self -> width / 2.0 , y = self -> height / 2.0 ;
907839 double line_width = thickness_as_float (self , level , true);
908- double radius = fmax (0 , fmin (x , y ) - line_width / 2.0 );
840+ double radius = fmax (0 , fmin (x , y ) - 1 - line_width / 2.0 );
909841 Circle c = circle (x , y , radius , start_degrees , end_degrees );
910- draw_parametrized_curve_with_derivative (self , & c , line_width , circle_x , circle_y , circle_prime_x , circle_prime_y );
842+ uint leftover = minus (self -> height , 2 * (uint )ceil (radius ) + 1 ) / 2 ;
843+ ClipRect cr = {.top = leftover , .y_end = self -> height - leftover , .x_end = self -> width };
844+ draw_parametrized_curve_with_derivative_and_antialiasing (
845+ self , & c , line_width , circle_x , circle_y , circle_prime_x , circle_prime_y , 0 , 0 , & cr );
911846}
912847
913848static void
@@ -933,7 +868,7 @@ static void
933868draw_fish_eye (Canvas * self , uint level UNUSED ) {
934869 double x = self -> width / 2. , y = self -> height / 2. ;
935870 double radius = fmin (x , y );
936- uint leftover = minus (self -> height , 2 * (uint )ceil (radius )) / 2 ;
871+ uint leftover = minus (self -> height , 2 * (uint )ceil (radius ) + 1 ) / 2 ;
937872 double central_radius = (2. /3. ) * radius ;
938873 fill_circle_of_radius (self , x , y , central_radius , 255 );
939874 double line_width = fmax (1. * self -> supersample_factor , (radius - central_radius ) / 2.5 );
@@ -1698,19 +1633,19 @@ START_ALLOW_CASE_RANGE
16981633 C (L'' , progress_bar , MIDDLE , true);
16991634 C (L'' , progress_bar , RIGHT , true);
17001635
1701- S (L'' , spinner , 1 , 235 , 305 );
1702- S (L'' , spinner , 1 , 270 , 390 );
1703- S (L'' , spinner , 1 , 315 , 470 );
1704- S (L'' , spinner , 1 , 360 , 540 );
1705- S (L'' , spinner , 1 , 80 , 220 );
1706- S (L'' , spinner , 1 , 170 , 270 );
1707- S (L'○' , spinner , 0 , 0 , 360 );
1708- S (L'◜' , spinner , 1 , 180 , 270 );
1709- S (L'◝' , spinner , 1 , 270 , 360 );
1710- S (L'◞' , spinner , 1 , 360 , 450 );
1711- S (L'◟' , spinner , 1 , 450 , 540 );
1712- S (L'◠' , spinner , 1 , 180 , 360 );
1713- S (L'◡' , spinner , 1 , 0 , 180 );
1636+ C (L'' , spinner , 1 , 235 , 305 );
1637+ C (L'' , spinner , 1 , 270 , 390 );
1638+ C (L'' , spinner , 1 , 315 , 470 );
1639+ C (L'' , spinner , 1 , 360 , 540 );
1640+ C (L'' , spinner , 1 , 80 , 220 );
1641+ C (L'' , spinner , 1 , 170 , 270 );
1642+ C (L'○' , spinner , 0 , 0 , 360 );
1643+ C (L'◜' , spinner , 1 , 180 , 270 );
1644+ C (L'◝' , spinner , 1 , 270 , 360 );
1645+ C (L'◞' , spinner , 1 , 360 , 450 );
1646+ C (L'◟' , spinner , 1 , 450 , 540 );
1647+ C (L'◠' , spinner , 1 , 180 , 360 );
1648+ C (L'◡' , spinner , 1 , 0 , 180 );
17141649 S (L'●' , fill_circle , 1.0 , 0 , false);
17151650 S (L'◉' , draw_fish_eye , 0 );
17161651
0 commit comments