@@ -1797,11 +1797,15 @@ static int
17971797flood_fill_inner (SDL_Surface * surf , int x1 , int y1 , Uint32 new_color ,
17981798 SDL_Surface * pattern , int * drawn_area )
17991799{
1800+ //breadth first flood fill, like graph search
18001801 SDL_Rect cliprect ;
1802+ size_t mask_idx ;
18011803
18021804 SDL_GetClipRect (surf , & cliprect );
18031805 size_t frontier_bufsize = 8 , frontier_size = 1 , next_frontier_size = 0 ;
18041806
1807+ //Instead of a queue, we use two arrays and swap them between steps.
1808+ //This makes implementation easier, especially memory management.
18051809 struct point2d * frontier =
18061810 malloc (frontier_bufsize * sizeof (struct point2d ));
18071811 if (frontier == NULL ) {
@@ -1815,8 +1819,9 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
18151819 free (frontier );
18161820 return -1 ;
18171821 }
1818- size_t mask_size = cliprect .w * cliprect .h ;
18191822
1823+ //2D bitmask for queued nodes
1824+ size_t mask_size = cliprect .w * cliprect .h ;
18201825 unsigned int * mask = calloc ((mask_size ) / 8 + 1 , sizeof (unsigned int ));
18211826 if (mask == NULL ) {
18221827 free (frontier );
@@ -1827,6 +1832,7 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
18271832 Uint32 old_color = 0 ;
18281833 Uint8 * pix ;
18291834
1835+ //Von Neumann neighbourhood
18301836 int VN_X [] = {0 , 0 , 1 , -1 };
18311837 int VN_Y [] = {1 , -1 , 0 , 0 };
18321838
@@ -1841,6 +1847,7 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
18411847 pix );
18421848
18431849 if (pattern == NULL && old_color == new_color ) {
1850+ //not an error, but nothing to do here
18441851 free (frontier );
18451852 free (mask );
18461853 free (frontier_next );
@@ -1850,18 +1857,19 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
18501857 frontier [0 ].x = x1 ;
18511858 frontier [0 ].y = y1 ;
18521859
1860+ //mark starting point already queued
1861+ mask_idx = (y1 - cliprect .y ) * cliprect .w + (x1 - cliprect .x );
1862+ _bitarray_set (mask , mask_idx , SDL_TRUE );
1863+
18531864 while (frontier_size != 0 ) {
18541865 next_frontier_size = 0 ;
18551866
18561867 for (size_t i = 0 ; i < frontier_size ; i ++ ) {
18571868 unsigned int x = frontier [i ].x ;
18581869 unsigned int y = frontier [i ].y ;
1859- size_t mask_idx = (y - cliprect .y ) * cliprect .w + (x - cliprect .x );
18601870
18611871 Uint32 current_color = 0 ;
18621872
1863- _bitarray_set (mask , mask_idx , SDL_TRUE );
1864-
18651873 SURF_GET_AT (current_color , surf , x , y , (Uint8 * )surf -> pixels ,
18661874 surf -> format , pix );
18671875
@@ -1874,13 +1882,13 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
18741882 (Uint8 * )pattern -> pixels , pattern -> format , pix );
18751883 }
18761884
1885+ //clipping and color mapping have already happened here
18771886 unsafe_set_at (surf , x , y , new_color );
18781887 add_pixel_to_drawn_list (x , y , drawn_area );
18791888
18801889 for (int n = 0 ; n < 4 ; n ++ ) {
18811890 long nx = x + VN_X [n ];
18821891 long ny = y + VN_Y [n ];
1883- SDL_bool found_in_frontier = SDL_FALSE ;
18841892
18851893 if (!(nx >= cliprect .x && nx < cliprect .x + cliprect .w &&
18861894 ny >= cliprect .y && ny < cliprect .y + cliprect .h )) {
@@ -1891,12 +1899,11 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
18911899 if (_bitarray_get (mask , mask_idx ))
18921900 continue ;
18931901
1902+ //only queue node once
18941903 _bitarray_set (mask , mask_idx , SDL_TRUE );
1895- if (found_in_frontier ) {
1896- continue ;
1897- }
18981904
18991905 if (next_frontier_size == frontier_bufsize ) {
1906+ //grow frontier arrays
19001907 struct point2d * old_buf = frontier_next ;
19011908
19021909 frontier_bufsize *= 4 ;
@@ -1927,6 +1934,7 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
19271934 next_frontier_size ++ ;
19281935 }
19291936 }
1937+ //swap buffers
19301938 struct point2d * temp_buf ;
19311939 temp_buf = frontier ;
19321940 frontier = frontier_next ;
0 commit comments