@@ -1003,12 +1003,6 @@ compare_int(const void *a, const void *b)
10031003 return (* (const int * )a ) - (* (const int * )b );
10041004}
10051005
1006- static int
1007- sign (int x , int y )
1008- {
1009- return (x > 0 ) ? 1 : ((x < 0 ) ? -1 : y );
1010- }
1011-
10121006static Uint32
10131007get_antialiased_color (SDL_Surface * surf , int x , int y , Uint32 original_color ,
10141008 float brightness , int blend )
@@ -1064,7 +1058,7 @@ add_pixel_to_drawn_list(int x, int y, int *pts)
10641058}
10651059
10661060static void
1067- add_line_to_drawn_list (int x1 , int y1 , int x2 , int * pts )
1061+ add_line_to_drawn_list (int x1 , int y1 , int x2 , int y2 , int * pts )
10681062{
10691063 if (x1 < pts [0 ]) {
10701064 pts [0 ] = x1 ;
@@ -1075,72 +1069,34 @@ add_line_to_drawn_list(int x1, int y1, int x2, int *pts)
10751069 if (x2 > pts [2 ]) {
10761070 pts [2 ] = x2 ;
10771071 }
1078- if (y1 > pts [3 ]) {
1079- pts [3 ] = y1 ;
1072+ if (y2 > pts [3 ]) {
1073+ pts [3 ] = y2 ;
10801074 }
10811075}
10821076
10831077static int
1084- clip_line (SDL_Surface * surf , int * x1 , int * y1 , int * x2 , int * y2 )
1078+ clip_line (SDL_Surface * surf , int * x1 , int * y1 , int * x2 , int * y2 , int width ,
1079+ int xinc )
10851080{
1086- int p1 = * x1 - * x2 ;
1087- int p2 = - p1 ;
1088- int p3 = * y1 - * y2 ;
1089- int p4 = - p3 ;
1090- int q1 = * x1 - surf -> clip_rect .x ;
1091- int q2 = surf -> clip_rect .w + surf -> clip_rect .x - * x1 ;
1092- int q3 = * y1 - surf -> clip_rect .y ;
1093- int q4 = surf -> clip_rect .h + surf -> clip_rect .y - * y1 ;
1094- int old_x1 = * x1 ;
1095- int old_y1 = * y1 ;
1096- double nmax = 0 ;
1097- double pmin = 1 ;
1098- double r1 , r2 ;
1099- if ((p1 == 0 && q1 < 0 ) || (p2 == 0 && q2 < 0 ) || (p3 == 0 && q3 < 0 ) ||
1100- (p4 == 0 && q4 < 0 ))
1101- return 0 ;
1102- if (p1 ) {
1103- r1 = (double )q1 / p1 ;
1104- r2 = (double )q2 / p2 ;
1105- if (p1 < 0 ) {
1106- if (r1 > nmax )
1107- nmax = r1 ;
1108- if (r2 < pmin )
1109- pmin = r2 ;
1110- }
1111- else {
1112- if (r2 > nmax )
1113- nmax = r2 ;
1114- if (r1 < pmin )
1115- pmin = r1 ;
1116- }
1081+ int left , right , top , bottom ;
1082+ if (xinc ) {
1083+ left = MIN (* x1 , * x2 ) - width ;
1084+ right = MAX (* x1 , * x2 ) + width ;
1085+ top = MIN (* y1 , * y2 );
1086+ bottom = MAX (* y1 , * y2 );
11171087 }
1118- if (p3 ) {
1119- r1 = (double )q3 / p3 ;
1120- r2 = (double )q4 / p4 ;
1121- if (p3 < 0 ) {
1122- if (r1 > nmax )
1123- nmax = r1 ;
1124- if (r2 < pmin )
1125- pmin = r2 ;
1126- }
1127- else {
1128- if (r2 > nmax )
1129- nmax = r2 ;
1130- if (r1 < pmin )
1131- pmin = r1 ;
1132- }
1133- }
1134- if (nmax > pmin )
1088+ else {
1089+ left = MIN (* x1 , * x2 );
1090+ right = MAX (* x1 , * x2 );
1091+ top = MIN (* y1 , * y2 ) - width ;
1092+ bottom = MAX (* y1 , * y2 ) + width ;
1093+ }
1094+ if (surf -> clip_rect .x > right || surf -> clip_rect .y > bottom ||
1095+ surf -> clip_rect .x + surf -> clip_rect .w <= left ||
1096+ surf -> clip_rect .y + surf -> clip_rect .h <= top ) {
11351097 return 0 ;
1136- * x1 =
1137- old_x1 + (int )(p2 * nmax < 0 ? (p2 * nmax - 0.5 ) : (p2 * nmax + 0.5 ));
1138- * y1 =
1139- old_y1 + (int )(p4 * nmax < 0 ? (p4 * nmax - 0.5 ) : (p4 * nmax + 0.5 ));
1140- * x2 =
1141- old_x1 + (int )(p2 * pmin < 0 ? (p2 * pmin - 0.5 ) : (p2 * pmin + 0.5 ));
1142- * y2 =
1143- old_y1 + (int )(p4 * pmin < 0 ? (p4 * pmin - 0.5 ) : (p4 * pmin + 0.5 ));
1098+ }
1099+
11441100 return 1 ;
11451101}
11461102
@@ -1425,6 +1381,42 @@ drawhorzline(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2)
14251381 }
14261382}
14271383
1384+ static void
1385+ drawvertline (SDL_Surface * surf , Uint32 color , int y1 , int x1 , int y2 )
1386+ {
1387+ Uint8 * pixel , * end ;
1388+
1389+ pixel = ((Uint8 * )surf -> pixels ) + surf -> pitch * y1 ;
1390+ end = ((Uint8 * )surf -> pixels ) + surf -> pitch * y2 +
1391+ x1 * surf -> format -> BytesPerPixel ;
1392+ pixel += x1 * surf -> format -> BytesPerPixel ;
1393+ switch (surf -> format -> BytesPerPixel ) {
1394+ case 1 :
1395+ for (; pixel <= end ; pixel += surf -> pitch ) {
1396+ * pixel = (Uint8 )color ;
1397+ }
1398+ break ;
1399+ case 2 :
1400+ for (; pixel <= end ; pixel += surf -> pitch ) {
1401+ * (Uint16 * )pixel = (Uint16 )color ;
1402+ }
1403+ break ;
1404+ case 3 :
1405+ #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1406+ color <<= 8 ;
1407+ #endif
1408+ for (; pixel <= end ; pixel += surf -> pitch ) {
1409+ memcpy (pixel , & color , 3 * sizeof (Uint8 ));
1410+ }
1411+ break ;
1412+ default : /*case 4*/
1413+ for (; pixel <= end ; pixel += surf -> pitch ) {
1414+ * (Uint32 * )pixel = color ;
1415+ }
1416+ break ;
1417+ }
1418+ }
1419+
14281420static void
14291421drawhorzlineclip (SDL_Surface * surf , Uint32 color , int x1 , int y1 , int x2 )
14301422{
@@ -1474,117 +1466,98 @@ drawhorzlineclipbounding(SDL_Surface *surf, Uint32 color, int x1, int y1,
14741466 return ;
14751467 }
14761468
1477- add_line_to_drawn_list (x1 , y1 , x2 , pts );
1469+ add_line_to_drawn_list (x1 , y1 , x2 , y1 , pts );
14781470
14791471 drawhorzline (surf , color , x1 , y1 , x2 );
14801472}
14811473
1482- int
1483- inside_clip (SDL_Surface * surf , int x , int y )
1484- {
1485- if (x < surf -> clip_rect .x || x >= surf -> clip_rect .x + surf -> clip_rect .w ||
1486- y < surf -> clip_rect .y || y >= surf -> clip_rect .y + surf -> clip_rect .h )
1487- return 0 ;
1488- return 1 ;
1489- }
1490-
14911474static void
14921475draw_line_width (SDL_Surface * surf , Uint32 color , int x1 , int y1 , int x2 ,
14931476 int y2 , int width , int * drawn_area )
14941477{
1495- int dx , dy , err , e2 , sx , sy , y ;
1496- int left_top , right_bottom ;
1497- int end_x = x2 ;
1498- int end_y = y2 ;
1478+ int dx , dy , err , e2 , sx , sy , start_draw , end_draw ;
1479+ int end_x = surf -> clip_rect .x + surf -> clip_rect .w - 1 ;
1480+ int end_y = surf -> clip_rect .y + surf -> clip_rect .h - 1 ;
14991481 int xinc = 0 ;
1482+ int extra_width = 1 - (width % 2 );
1483+
1484+ if (width < 1 )
1485+ return ;
1486+ if (width == 1 ) {
1487+ draw_line (surf , x1 , y1 , x2 , y2 , color , drawn_area );
1488+ return ;
1489+ }
1490+
1491+ width = (width / 2 );
1492+
15001493 /* Decide which direction to grow (width/thickness). */
15011494 if (abs (x1 - x2 ) <= abs (y1 - y2 )) {
15021495 /* The line's thickness will be in the x direction. The top/bottom
15031496 * ends of the line will be flat. */
15041497 xinc = 1 ;
15051498 }
1499+
1500+ if (!clip_line (surf , & x1 , & y1 , & x2 , & y2 , width , xinc ))
1501+ return ;
1502+
1503+ if (x1 == x2 && y1 == y2 ) { /* Single point */
1504+ start_draw = MAX ((x1 - width ) + extra_width , surf -> clip_rect .x );
1505+ end_draw = MIN (end_x , x1 + width );
1506+ if (start_draw <= end_draw ) {
1507+ drawhorzline (surf , color , start_draw , y1 , end_draw );
1508+ add_line_to_drawn_list (start_draw , y1 , end_draw , y1 , drawn_area );
1509+ }
1510+ return ;
1511+ }
1512+ // Bresenham's line algorithm
15061513 dx = abs (x2 - x1 );
1507- sx = x1 < x2 ? 1 : -1 ;
15081514 dy = abs (y2 - y1 );
1509- sy = y1 < y2 ? 1 : -1 ;
1515+ sx = x2 > x1 ? 1 : -1 ;
1516+ sy = y2 > y1 ? 1 : -1 ;
15101517 err = (dx > dy ? dx : - dy ) / 2 ;
1511- if (clip_line (surf , & x1 , & y1 , & x2 , & y2 )) {
1512- if (width == 1 )
1513- draw_line (surf , x1 , y1 , x2 , y2 , color , drawn_area );
1514- else {
1515- if (xinc ) {
1516- left_top = x1 - (width - 1 ) / 2 ;
1517- right_bottom = x1 + width / 2 ;
1518+ if (xinc ) {
1519+ while (y1 != (y2 + sy )) {
1520+ if (surf -> clip_rect .y <= y1 && y1 <= end_y ) {
1521+ start_draw =
1522+ MAX ((x1 - width ) + extra_width , surf -> clip_rect .x );
1523+ end_draw = MIN (end_x , x1 + width );
1524+ if (start_draw <= end_draw ) {
1525+ drawhorzline (surf , color , start_draw , y1 , end_draw );
1526+ add_line_to_drawn_list (start_draw , y1 , end_draw , y1 ,
1527+ drawn_area );
1528+ }
15181529 }
1519- else {
1520- left_top = y1 - (width - 1 ) / 2 ;
1521- right_bottom = y1 + width / 2 ;
1530+ e2 = err ;
1531+ if (e2 > - dx ) {
1532+ err -= dy ;
1533+ x1 += sx ;
15221534 }
1523- while ((sign (x1 - x2 , sx ) != sx ) || (sign (y1 - y2 , sy ) != sy )) {
1524- if (xinc )
1525- drawhorzlineclipbounding (surf , color , left_top , y1 ,
1526- right_bottom , drawn_area );
1527- else {
1528- for (y = left_top ; y <= right_bottom ; y ++ )
1529- set_and_check_rect (surf , x1 , y , color , drawn_area );
1530- }
1531- e2 = err ;
1532- if (e2 > - dx ) {
1533- err -= dy ;
1534- x1 += sx ;
1535- if (xinc ) {
1536- left_top += sx ;
1537- right_bottom += sx ;
1538- }
1539- }
1540- if (e2 < dy ) {
1541- err += dx ;
1542- y1 += sy ;
1543- if (!xinc ) {
1544- left_top += sy ;
1545- right_bottom += sy ;
1546- }
1547- }
1535+ if (e2 < dy ) {
1536+ err += dx ;
1537+ y1 += sy ;
15481538 }
1549- if (xinc ) {
1550- while (y1 != end_y && (inside_clip (surf , left_top , y1 ) ||
1551- inside_clip (surf , right_bottom , y1 ))) {
1552- drawhorzlineclipbounding (surf , color , left_top , y1 ,
1553- right_bottom , drawn_area );
1554- e2 = err ;
1555- if (e2 > - dx ) {
1556- err -= dy ;
1557- x1 += sx ;
1558- left_top += sx ;
1559- right_bottom += sx ;
1560- }
1561- if (e2 < dy ) {
1562- err += dx ;
1563- y1 += sy ;
1564- }
1539+ }
1540+ }
1541+ else {
1542+ while (x1 != (x2 + sx )) {
1543+ if (surf -> clip_rect .x <= x1 && x1 <= end_x ) {
1544+ start_draw =
1545+ MAX ((y1 - width ) + extra_width , surf -> clip_rect .y );
1546+ end_draw = MIN (end_y , y1 + width );
1547+ if (start_draw <= end_draw ) {
1548+ drawvertline (surf , color , start_draw , x1 , end_draw );
1549+ add_line_to_drawn_list (x1 , start_draw , x1 , end_draw ,
1550+ drawn_area );
15651551 }
1566- drawhorzlineclipbounding (surf , color , left_top , y1 ,
1567- right_bottom , drawn_area );
15681552 }
1569- else {
1570- while (x1 != end_x && (inside_clip (surf , x1 , left_top ) ||
1571- inside_clip (surf , x1 , right_bottom ))) {
1572- for (y = left_top ; y <= right_bottom ; y ++ )
1573- set_and_check_rect (surf , x1 , y , color , drawn_area );
1574- e2 = err ;
1575- if (e2 > - dx ) {
1576- err -= dy ;
1577- x1 += sx ;
1578- }
1579- if (e2 < dy ) {
1580- err += dx ;
1581- y1 += sy ;
1582- left_top += sy ;
1583- right_bottom += sy ;
1584- }
1585- }
1586- for (y = left_top ; y <= right_bottom ; y ++ )
1587- set_and_check_rect (surf , x1 , y , color , drawn_area );
1553+ e2 = err ;
1554+ if (e2 > - dx ) {
1555+ err -= dy ;
1556+ x1 += sx ;
1557+ }
1558+ if (e2 < dy ) {
1559+ err += dx ;
1560+ y1 += sy ;
15881561 }
15891562 }
15901563 }
0 commit comments