@@ -1797,11 +1797,15 @@ static int
1797
1797
flood_fill_inner (SDL_Surface * surf , int x1 , int y1 , Uint32 new_color ,
1798
1798
SDL_Surface * pattern , int * drawn_area )
1799
1799
{
1800
+ //breadth first flood fill, like graph search
1800
1801
SDL_Rect cliprect ;
1802
+ size_t mask_idx ;
1801
1803
1802
1804
SDL_GetClipRect (surf , & cliprect );
1803
1805
size_t frontier_bufsize = 8 , frontier_size = 1 , next_frontier_size = 0 ;
1804
1806
1807
+ //Instead of a queue, we use two arrays and swap them between steps.
1808
+ //This makes implementation easier, especially memory management.
1805
1809
struct point2d * frontier =
1806
1810
malloc (frontier_bufsize * sizeof (struct point2d ));
1807
1811
if (frontier == NULL ) {
@@ -1815,8 +1819,9 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
1815
1819
free (frontier );
1816
1820
return -1 ;
1817
1821
}
1818
- size_t mask_size = cliprect .w * cliprect .h ;
1819
1822
1823
+ //2D bitmask for queued nodes
1824
+ size_t mask_size = cliprect .w * cliprect .h ;
1820
1825
unsigned int * mask = calloc ((mask_size ) / 8 + 1 , sizeof (unsigned int ));
1821
1826
if (mask == NULL ) {
1822
1827
free (frontier );
@@ -1827,6 +1832,7 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
1827
1832
Uint32 old_color = 0 ;
1828
1833
Uint8 * pix ;
1829
1834
1835
+ //Von Neumann neighbourhood
1830
1836
int VN_X [] = {0 , 0 , 1 , -1 };
1831
1837
int VN_Y [] = {1 , -1 , 0 , 0 };
1832
1838
@@ -1841,6 +1847,7 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
1841
1847
pix );
1842
1848
1843
1849
if (pattern == NULL && old_color == new_color ) {
1850
+ //not an error, but nothing to do here
1844
1851
free (frontier );
1845
1852
free (mask );
1846
1853
free (frontier_next );
@@ -1850,18 +1857,19 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
1850
1857
frontier [0 ].x = x1 ;
1851
1858
frontier [0 ].y = y1 ;
1852
1859
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
+
1853
1864
while (frontier_size != 0 ) {
1854
1865
next_frontier_size = 0 ;
1855
1866
1856
1867
for (size_t i = 0 ; i < frontier_size ; i ++ ) {
1857
1868
unsigned int x = frontier [i ].x ;
1858
1869
unsigned int y = frontier [i ].y ;
1859
- size_t mask_idx = (y - cliprect .y ) * cliprect .w + (x - cliprect .x );
1860
1870
1861
1871
Uint32 current_color = 0 ;
1862
1872
1863
- _bitarray_set (mask , mask_idx , SDL_TRUE );
1864
-
1865
1873
SURF_GET_AT (current_color , surf , x , y , (Uint8 * )surf -> pixels ,
1866
1874
surf -> format , pix );
1867
1875
@@ -1874,13 +1882,13 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
1874
1882
(Uint8 * )pattern -> pixels , pattern -> format , pix );
1875
1883
}
1876
1884
1885
+ //clipping and color mapping have already happened here
1877
1886
unsafe_set_at (surf , x , y , new_color );
1878
1887
add_pixel_to_drawn_list (x , y , drawn_area );
1879
1888
1880
1889
for (int n = 0 ; n < 4 ; n ++ ) {
1881
1890
long nx = x + VN_X [n ];
1882
1891
long ny = y + VN_Y [n ];
1883
- SDL_bool found_in_frontier = SDL_FALSE ;
1884
1892
1885
1893
if (!(nx >= cliprect .x && nx < cliprect .x + cliprect .w &&
1886
1894
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,
1891
1899
if (_bitarray_get (mask , mask_idx ))
1892
1900
continue ;
1893
1901
1902
+ //only queue node once
1894
1903
_bitarray_set (mask , mask_idx , SDL_TRUE );
1895
- if (found_in_frontier ) {
1896
- continue ;
1897
- }
1898
1904
1899
1905
if (next_frontier_size == frontier_bufsize ) {
1906
+ //grow frontier arrays
1900
1907
struct point2d * old_buf = frontier_next ;
1901
1908
1902
1909
frontier_bufsize *= 4 ;
@@ -1927,6 +1934,7 @@ flood_fill_inner(SDL_Surface *surf, int x1, int y1, Uint32 new_color,
1927
1934
next_frontier_size ++ ;
1928
1935
}
1929
1936
}
1937
+ //swap buffers
1930
1938
struct point2d * temp_buf ;
1931
1939
temp_buf = frontier ;
1932
1940
frontier = frontier_next ;
0 commit comments