@@ -44,17 +44,18 @@ draw_line_width(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color,
4444static void
4545draw_line (SDL_Surface * surf , SDL_Rect surf_clip_rect , int x1 , int y1 , int x2 ,
4646 int y2 , Uint32 color , int * drawn_area );
47- void
48- line_width_corners (float from_x , float from_y , float to_x , float to_y ,
49- int width , float * x1 , float * y1 , float * x2 , float * y2 ,
50- float * x3 , float * y3 , float * x4 , float * y4 );
5147static void
5248draw_aaline (SDL_Surface * surf , SDL_Rect surf_clip_rect ,
5349 PG_PixelFormat * surf_format , Uint32 color , float startx ,
5450 float starty , float endx , float endy , int * drawn_area ,
5551 int disable_first_endpoint , int disable_second_endpoint ,
5652 int extra_pixel_for_aalines );
5753static void
54+ draw_aaline_width (SDL_Surface * surf , SDL_Rect surf_clip_rect ,
55+ PG_PixelFormat * surf_format , Uint32 color , float from_x ,
56+ float from_y , float to_x , float to_y , int width ,
57+ int * drawn_area );
58+ static void
5859draw_arc (SDL_Surface * surf , SDL_Rect surf_clip_rect , int x_center ,
5960 int y_center , int radius1 , int radius2 , int width , double angle_start ,
6061 double angle_stop , Uint32 color , int * drawn_area );
@@ -188,15 +189,8 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs)
188189 }
189190
190191 if (width > 1 ) {
191- float x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 ;
192- line_width_corners (startx , starty , endx , endy , width , & x1 , & y1 , & x2 ,
193- & y2 , & x3 , & y3 , & x4 , & y4 );
194- draw_line_width (surf , surf_clip_rect , color , (int )startx , (int )starty ,
195- (int )endx , (int )endy , width , drawn_area );
196- draw_aaline (surf , surf_clip_rect , surf_format , color , x1 , y1 , x2 , y2 ,
197- drawn_area , 0 , 0 , 0 );
198- draw_aaline (surf , surf_clip_rect , surf_format , color , x3 , y3 , x4 , y4 ,
199- drawn_area , 0 , 0 , 0 );
192+ draw_aaline_width (surf , surf_clip_rect , surf_format , color , startx ,
193+ starty , endx , endy , width , drawn_area );
200194 }
201195 else {
202196 draw_aaline (surf , surf_clip_rect , surf_format , color , startx , starty ,
@@ -1831,6 +1825,37 @@ drawhorzlineclipbounding(SDL_Surface *surf, SDL_Rect surf_clip_rect,
18311825 drawhorzline (surf , color , x1 , y1 , x2 );
18321826}
18331827
1828+ static void
1829+ drawvertlineclipbounding (SDL_Surface * surf , SDL_Rect surf_clip_rect ,
1830+ Uint32 color , int y1 , int x1 , int y2 , int * pts )
1831+ {
1832+ if (x1 < surf_clip_rect .x || x1 >= surf_clip_rect .x + surf_clip_rect .w ) {
1833+ return ;
1834+ }
1835+
1836+ if (y2 < y1 ) {
1837+ int temp = y1 ;
1838+ y1 = y2 ;
1839+ y2 = temp ;
1840+ }
1841+
1842+ y1 = MAX (y1 , surf_clip_rect .y );
1843+ y2 = MIN (y2 , surf_clip_rect .y + surf_clip_rect .h - 1 );
1844+
1845+ if (y2 < surf_clip_rect .y || y1 >= surf_clip_rect .y + surf_clip_rect .h ) {
1846+ return ;
1847+ }
1848+
1849+ if (y1 == y2 ) {
1850+ set_and_check_rect (surf , surf_clip_rect , x1 , y1 , color , pts );
1851+ return ;
1852+ }
1853+
1854+ add_line_to_drawn_list (x1 , y1 , x1 , y2 , pts );
1855+
1856+ drawvertline (surf , color , y1 , x1 , y2 );
1857+ }
1858+
18341859void
18351860swap_coordinates (int * x1 , int * y1 , int * x2 , int * y2 )
18361861{
@@ -1986,36 +2011,295 @@ draw_line_width(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color,
19862011 }
19872012}
19882013
1989- // Calculates 4 points, representing corners of draw_line_width()
1990- // first two points assemble left line and second two - right line
1991- void
1992- line_width_corners (float from_x , float from_y , float to_x , float to_y ,
1993- int width , float * x1 , float * y1 , float * x2 , float * y2 ,
1994- float * x3 , float * y3 , float * x4 , float * y4 )
2014+ static void
2015+ draw_aaline_width (SDL_Surface * surf , SDL_Rect surf_clip_rect ,
2016+ PG_PixelFormat * surf_format , Uint32 color , float from_x ,
2017+ float from_y , float to_x , float to_y , int width ,
2018+ int * drawn_area )
19952019{
1996- float aa_width = (float )width / 2 ;
1997- float extra_width = (1.0f - (width % 2 )) / 2 ;
1998- int steep = fabs (to_x - from_x ) <= fabs (to_y - from_y );
2020+ float gradient , dx , dy , intersect_y , brightness ;
2021+ int x , x_pixel_start , x_pixel_end , start_draw , end_draw ;
2022+ Uint32 pixel_color ;
2023+ float y_endpoint , clip_left , clip_right , clip_top , clip_bottom ;
2024+ int steep , y ;
2025+ int extra_width = 1 - (width % 2 );
2026+
2027+ width = (width / 2 );
2028+
2029+ dx = to_x - from_x ;
2030+ dy = to_y - from_y ;
2031+ steep = fabs (dx ) < fabs (dy );
2032+
2033+ /* Single point.
2034+ * A line with length 0 is drawn as a single pixel at full brightness. */
2035+ if (fabs (dx ) < 0.0001 && fabs (dy ) < 0.0001 ) {
2036+ x = (int )floor (from_x + 0.5 );
2037+ y = (int )floor (from_y + 0.5 );
2038+ pixel_color = get_antialiased_color (surf , surf_clip_rect , surf_format ,
2039+ x , y , color , 1 );
2040+ set_and_check_rect (surf , surf_clip_rect , x , y , pixel_color ,
2041+ drawn_area );
2042+ if (dx != 0 && dy != 0 ) {
2043+ if (steep ) {
2044+ start_draw = (int )(x - width + extra_width );
2045+ end_draw = (int )(x + width ) - 1 ;
2046+ drawhorzlineclipbounding (surf , surf_clip_rect , color ,
2047+ start_draw , y , end_draw , drawn_area );
2048+ }
2049+ else {
2050+ start_draw = (int )(y - width + extra_width );
2051+ end_draw = (int )(y + width ) - 1 ;
2052+ drawvertlineclipbounding (surf , surf_clip_rect , color ,
2053+ start_draw , x , end_draw , drawn_area );
2054+ }
2055+ }
2056+ return ;
2057+ }
2058+
2059+ /* To draw correctly the pixels at the border of the clipping area when
2060+ * the line crosses it, we need to clip it one pixel wider in all four
2061+ * directions, and add width */
2062+ clip_left = (float )surf_clip_rect .x - 1.0f ;
2063+ clip_right = (float )clip_left + surf_clip_rect .w + 1.0f ;
2064+ clip_top = (float )surf_clip_rect .y - 1.0f ;
2065+ clip_bottom = (float )clip_top + surf_clip_rect .h + 1.0f ;
19992066
20002067 if (steep ) {
2001- * x1 = from_x + extra_width + aa_width ;
2002- * y1 = from_y ;
2003- * x2 = to_x + extra_width + aa_width ;
2004- * y2 = to_y ;
2005- * x3 = from_x + extra_width - aa_width ;
2006- * y3 = from_y ;
2007- * x4 = to_x + extra_width - aa_width ;
2008- * y4 = to_y ;
2068+ swap (& from_x , & from_y );
2069+ swap (& to_x , & to_y );
2070+ swap (& dx , & dy );
2071+ swap (& clip_left , & clip_top );
2072+ swap (& clip_right , & clip_bottom );
2073+ }
2074+ if (dx < 0 ) {
2075+ swap (& from_x , & to_x );
2076+ swap (& from_y , & to_y );
2077+ dx = - dx ;
2078+ dy = - dy ;
2079+ }
2080+
2081+ if (to_x <= clip_left || from_x >= clip_right ) {
2082+ /* The line is completely to the side of the surface */
2083+ return ;
2084+ }
2085+
2086+ /* Note. There is no need to guard against a division by zero here. If dx
2087+ * was zero then either we had a single point (and we've returned) or it
2088+ * has been swapped with a non-zero dy. */
2089+ gradient = dy / dx ;
2090+
2091+ /* No need to waste CPU cycles on pixels not on the surface. */
2092+ if (from_x < clip_left + 1 ) {
2093+ from_y += gradient * (clip_left + 1 - from_x );
2094+ from_x = clip_left + 1 ;
2095+ }
2096+ if (to_x > clip_right - 1 ) {
2097+ to_y += gradient * (clip_right - 1 - to_x );
2098+ to_x = clip_right - 1 ;
2099+ }
2100+
2101+ if (gradient > 0.0f ) {
2102+ if (from_x < clip_left + 1 ) {
2103+ /* from_ is the topmost endpoint */
2104+ if (to_y <= clip_top || from_y >= clip_bottom ) {
2105+ /* The line does not enter the surface */
2106+ return ;
2107+ }
2108+ if (from_y < clip_top - width ) {
2109+ from_x += (clip_top - width - from_y ) / gradient ;
2110+ from_y = clip_top - width ;
2111+ }
2112+ if (to_y > clip_bottom + width ) {
2113+ to_x += (clip_bottom + width - to_y ) / gradient ;
2114+ to_y = clip_bottom + width ;
2115+ }
2116+ }
20092117 }
20102118 else {
2011- * x1 = from_x ;
2012- * y1 = from_y + extra_width + aa_width ;
2013- * x2 = to_x ;
2014- * y2 = to_y + extra_width + aa_width ;
2015- * x3 = from_x ;
2016- * y3 = from_y + extra_width - aa_width ;
2017- * x4 = to_x ;
2018- * y4 = to_y + extra_width - aa_width ;
2119+ if (to_x > clip_right - 1 ) {
2120+ /* to_ is the topmost endpoint */
2121+ if (from_y <= clip_top || to_y >= clip_bottom ) {
2122+ /* The line does not enter the surface */
2123+ return ;
2124+ }
2125+ if (to_y < clip_top - width ) {
2126+ to_x += (clip_top - width - to_y ) / gradient ;
2127+ to_y = clip_top - width ;
2128+ }
2129+ if (from_y > clip_bottom + width ) {
2130+ from_x += (clip_bottom + width - from_y ) / gradient ;
2131+ from_y = clip_bottom + width ;
2132+ }
2133+ }
2134+ }
2135+
2136+ /* By moving the points one pixel down, we can assume y is never negative.
2137+ * That permit us to use (int)y to round down instead of having to use
2138+ * floor(y). We then draw the pixels one higher.*/
2139+ from_y += 1.0f ;
2140+ to_y += 1.0f ;
2141+
2142+ /* Handle endpoints separately */
2143+ /* First endpoint */
2144+ x_pixel_start = (int )from_x ;
2145+ y_endpoint = intersect_y = from_y + gradient * (x_pixel_start - from_x );
2146+ if (to_x > clip_left + 1.0f ) {
2147+ brightness = y_endpoint - (int )y_endpoint ;
2148+ if (steep ) {
2149+ x = (int )y_endpoint ;
2150+ y = x_pixel_start ;
2151+ }
2152+ else {
2153+ x = x_pixel_start ;
2154+ y = (int )y_endpoint ;
2155+ }
2156+ if ((int )y_endpoint < y_endpoint ) {
2157+ if (steep ) {
2158+ pixel_color =
2159+ get_antialiased_color (surf , surf_clip_rect , surf_format ,
2160+ x + width , y , color , brightness );
2161+ set_and_check_rect (surf , surf_clip_rect , x + width , y ,
2162+ pixel_color , drawn_area );
2163+ }
2164+ else {
2165+ pixel_color =
2166+ get_antialiased_color (surf , surf_clip_rect , surf_format , x ,
2167+ y + width , color , brightness );
2168+ set_and_check_rect (surf , surf_clip_rect , x , y + width ,
2169+ pixel_color , drawn_area );
2170+ }
2171+ }
2172+ brightness = 1 - brightness ;
2173+ if (steep ) {
2174+ pixel_color =
2175+ get_antialiased_color (surf , surf_clip_rect , surf_format ,
2176+ x - width , y , color , brightness );
2177+ set_and_check_rect (surf , surf_clip_rect ,
2178+ x - width + extra_width - 1 , y , pixel_color ,
2179+ drawn_area );
2180+ start_draw = (int )(x - width + extra_width );
2181+ end_draw = (int )(x + width ) - 1 ;
2182+ drawhorzlineclipbounding (surf , surf_clip_rect , color , start_draw ,
2183+ y , end_draw , drawn_area );
2184+ }
2185+ else {
2186+ pixel_color = get_antialiased_color (
2187+ surf , surf_clip_rect , surf_format , x ,
2188+ y - width + extra_width - 1 , color , brightness );
2189+ set_and_check_rect (surf , surf_clip_rect , x ,
2190+ y - width + extra_width - 1 , pixel_color ,
2191+ drawn_area );
2192+ start_draw = (int )(y - width + extra_width );
2193+ end_draw = (int )(y + width ) - 1 ;
2194+ drawvertlineclipbounding (surf , surf_clip_rect , color , start_draw ,
2195+ x , end_draw , drawn_area );
2196+ }
2197+ intersect_y += gradient ;
2198+ x_pixel_start ++ ;
2199+ }
2200+
2201+ /* Second endpoint */
2202+ x_pixel_end = (int )ceil (to_x );
2203+ if (from_x < clip_right - 1.0f ) {
2204+ y_endpoint = to_y + gradient * (x_pixel_end - to_x );
2205+ brightness = y_endpoint - (int )y_endpoint ;
2206+ if (steep ) {
2207+ x = (int )y_endpoint ;
2208+ y = x_pixel_end ;
2209+ }
2210+ else {
2211+ x = x_pixel_end ;
2212+ y = (int )y_endpoint ;
2213+ }
2214+ if ((int )y_endpoint < y_endpoint ) {
2215+ if (steep ) {
2216+ pixel_color =
2217+ get_antialiased_color (surf , surf_clip_rect , surf_format ,
2218+ x + width , y , color , brightness );
2219+ set_and_check_rect (surf , surf_clip_rect , x + width , y ,
2220+ pixel_color , drawn_area );
2221+ }
2222+ else {
2223+ pixel_color =
2224+ get_antialiased_color (surf , surf_clip_rect , surf_format , x ,
2225+ y + width , color , brightness );
2226+ set_and_check_rect (surf , surf_clip_rect , x , y + width ,
2227+ pixel_color , drawn_area );
2228+ }
2229+ }
2230+ brightness = 1 - brightness ;
2231+ if (steep ) {
2232+ pixel_color = get_antialiased_color (
2233+ surf , surf_clip_rect , surf_format , x - width + extra_width - 1 ,
2234+ y , color , brightness );
2235+ set_and_check_rect (surf , surf_clip_rect ,
2236+ x - width + extra_width - 1 , y , pixel_color ,
2237+ drawn_area );
2238+ start_draw = (int )(x - width );
2239+ end_draw = (int )(x + width ) - 1 ;
2240+ drawhorzlineclipbounding (surf , surf_clip_rect , color , start_draw ,
2241+ y , end_draw , drawn_area );
2242+ }
2243+ else {
2244+ pixel_color = get_antialiased_color (
2245+ surf , surf_clip_rect , surf_format , x ,
2246+ y - width + extra_width - 1 , color , brightness );
2247+ set_and_check_rect (surf , surf_clip_rect , x ,
2248+ y - width + extra_width - 1 , pixel_color ,
2249+ drawn_area );
2250+ start_draw = (int )(y - width + extra_width );
2251+ end_draw = (int )(y + width ) - 1 ;
2252+ drawvertlineclipbounding (surf , surf_clip_rect , color , start_draw ,
2253+ x , end_draw , drawn_area );
2254+ }
2255+ }
2256+
2257+ /* main line drawing loop */
2258+ for (x = x_pixel_start ; x < x_pixel_end ; x ++ ) {
2259+ y = (int )intersect_y ;
2260+ if (steep ) {
2261+ brightness = 1 - intersect_y + y ;
2262+ pixel_color = get_antialiased_color (
2263+ surf , surf_clip_rect , surf_format , y - width + extra_width - 1 ,
2264+ x , color , brightness );
2265+ set_and_check_rect (surf , surf_clip_rect ,
2266+ y - width + extra_width - 1 , x , pixel_color ,
2267+ drawn_area );
2268+ if (y < intersect_y ) {
2269+ brightness = 1 - brightness ;
2270+ pixel_color =
2271+ get_antialiased_color (surf , surf_clip_rect , surf_format ,
2272+ y + width , x , color , brightness );
2273+ set_and_check_rect (surf , surf_clip_rect , y + width , x ,
2274+ pixel_color , drawn_area );
2275+ }
2276+ start_draw = (int )(y - width + extra_width );
2277+ end_draw = (int )(y + width ) - 1 ;
2278+ drawhorzlineclipbounding (surf , surf_clip_rect , color , start_draw ,
2279+ x , end_draw , drawn_area );
2280+ }
2281+ else {
2282+ brightness = 1 - intersect_y + y ;
2283+ pixel_color = get_antialiased_color (
2284+ surf , surf_clip_rect , surf_format , x ,
2285+ y - width + extra_width - 1 , color , brightness );
2286+ set_and_check_rect (surf , surf_clip_rect , x ,
2287+ y - width + extra_width - 1 , pixel_color ,
2288+ drawn_area );
2289+ if (y < intersect_y ) {
2290+ brightness = 1 - brightness ;
2291+ pixel_color =
2292+ get_antialiased_color (surf , surf_clip_rect , surf_format , x ,
2293+ y + width , color , brightness );
2294+ set_and_check_rect (surf , surf_clip_rect , x , y + width ,
2295+ pixel_color , drawn_area );
2296+ }
2297+ start_draw = (int )(y - width + extra_width );
2298+ end_draw = (int )(y + width ) - 1 ;
2299+ drawvertlineclipbounding (surf , surf_clip_rect , color , start_draw ,
2300+ x , end_draw , drawn_area );
2301+ }
2302+ intersect_y += gradient ;
20192303 }
20202304}
20212305
0 commit comments