@@ -44,17 +44,18 @@ draw_line_width(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color,
44
44
static void
45
45
draw_line (SDL_Surface * surf , SDL_Rect surf_clip_rect , int x1 , int y1 , int x2 ,
46
46
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 );
51
47
static void
52
48
draw_aaline (SDL_Surface * surf , SDL_Rect surf_clip_rect ,
53
49
PG_PixelFormat * surf_format , Uint32 color , float startx ,
54
50
float starty , float endx , float endy , int * drawn_area ,
55
51
int disable_first_endpoint , int disable_second_endpoint ,
56
52
int extra_pixel_for_aalines );
57
53
static 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
58
59
draw_arc (SDL_Surface * surf , SDL_Rect surf_clip_rect , int x_center ,
59
60
int y_center , int radius1 , int radius2 , int width , double angle_start ,
60
61
double angle_stop , Uint32 color , int * drawn_area );
@@ -188,15 +189,8 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs)
188
189
}
189
190
190
191
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 );
200
194
}
201
195
else {
202
196
draw_aaline (surf , surf_clip_rect , surf_format , color , startx , starty ,
@@ -1831,6 +1825,37 @@ drawhorzlineclipbounding(SDL_Surface *surf, SDL_Rect surf_clip_rect,
1831
1825
drawhorzline (surf , color , x1 , y1 , x2 );
1832
1826
}
1833
1827
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
+
1834
1859
void
1835
1860
swap_coordinates (int * x1 , int * y1 , int * x2 , int * y2 )
1836
1861
{
@@ -1986,36 +2011,295 @@ draw_line_width(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color,
1986
2011
}
1987
2012
}
1988
2013
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 )
1995
2019
{
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 ;
1999
2066
2000
2067
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
+ }
2009
2117
}
2010
2118
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 ;
2019
2303
}
2020
2304
}
2021
2305
0 commit comments