@@ -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
318325static void
319326draw_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+
329344static void
330345draw_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+
736753static void
737754draw_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