@@ -46,7 +46,9 @@ draw_line(SDL_Surface *surf, int x1, int y1, int x2, int y2, Uint32 color,
46
46
int * drawn_area );
47
47
static void
48
48
draw_aaline (SDL_Surface * surf , Uint32 color , float startx , float starty ,
49
- float endx , float endy , int * drawn_area );
49
+ float endx , float endy , int * drawn_area ,
50
+ int disable_first_endpoint , int disable_second_endpoint ,
51
+ int extra_pixel_for_aalines );
50
52
static void
51
53
draw_arc (SDL_Surface * surf , int x_center , int y_center , int radius1 ,
52
54
int radius2 , int width , double angle_start , double angle_stop ,
@@ -159,7 +161,7 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs)
159
161
return RAISE (PyExc_RuntimeError , "error locking surface" );
160
162
}
161
163
162
- draw_aaline (surf , color , startx , starty , endx , endy , drawn_area );
164
+ draw_aaline (surf , color , startx , starty , endx , endy , drawn_area , 0 , 0 , 0 );
163
165
164
166
if (!pgSurface_Unlock (surfobj )) {
165
167
return RAISE (PyExc_RuntimeError , "error unlocking surface" );
@@ -255,9 +257,13 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs)
255
257
SDL_Surface * surf = NULL ;
256
258
Uint32 color ;
257
259
float pts [4 ];
260
+ float pts_prev [4 ];
258
261
float * xlist , * ylist ;
259
262
float x , y ;
260
263
int l , t ;
264
+ int extra_px ;
265
+ int steep_prev ;
266
+ int steep_curr ;
261
267
PyObject * blend = NULL ;
262
268
int drawn_area [4 ] = {INT_MAX , INT_MAX , INT_MIN ,
263
269
INT_MIN }; /* Used to store bounding box values */
@@ -344,19 +350,84 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs)
344
350
return RAISE (PyExc_RuntimeError , "error locking surface" );
345
351
}
346
352
347
- for (loop = 1 ; loop < length ; ++ loop ) {
353
+ /* first line - if open, add endpoint pixels.*/
354
+ pts [0 ] = xlist [0 ];
355
+ pts [1 ] = ylist [0 ];
356
+ pts [2 ] = xlist [1 ];
357
+ pts [3 ] = ylist [1 ];
358
+
359
+ /* Previous points.
360
+ * Used to compare previous and current line.*/
361
+ pts_prev [0 ] = pts [0 ];
362
+ pts_prev [1 ] = pts [1 ];
363
+ pts_prev [2 ] = pts [2 ];
364
+ pts_prev [3 ] = pts [3 ];
365
+ steep_prev =
366
+ fabs (pts_prev [2 ] - pts_prev [0 ]) < fabs (pts_prev [3 ] - pts_prev [1 ]);
367
+ steep_curr = fabs (xlist [2 ] - pts [2 ]) < fabs (ylist [2 ] - pts [1 ]);
368
+ extra_px = steep_prev > steep_curr ;
369
+ if (closed ) {
370
+ draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area , 1 ,
371
+ 1 , extra_px );
372
+ }
373
+ else {
374
+ draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area , 0 ,
375
+ 1 , extra_px );
376
+ }
377
+
378
+ for (loop = 2 ; loop < length - 1 ; ++ loop ) {
348
379
pts [0 ] = xlist [loop - 1 ];
349
380
pts [1 ] = ylist [loop - 1 ];
350
381
pts [2 ] = xlist [loop ];
351
382
pts [3 ] = ylist [loop ];
352
- draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area );
383
+
384
+ /* Comparing previous and current line.
385
+ * If one is steep and other is not, extra pixel must be drawn.*/
386
+ steep_prev =
387
+ fabs (pts_prev [2 ] - pts_prev [0 ]) < fabs (pts_prev [3 ] - pts_prev [1 ]);
388
+ steep_curr = fabs (pts [2 ] - pts [0 ]) < fabs (pts [3 ] - pts [1 ]);
389
+ extra_px = steep_prev != steep_curr ;
390
+ pts_prev [0 ] = pts [0 ];
391
+ pts_prev [1 ] = pts [1 ];
392
+ pts_prev [2 ] = pts [2 ];
393
+ pts_prev [3 ] = pts [3 ];
394
+ draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area , 1 ,
395
+ 1 , extra_px );
396
+ }
397
+
398
+ /* Last line - if open, add endpoint pixels. */
399
+ pts [0 ] = xlist [length - 2 ];
400
+ pts [1 ] = ylist [length - 2 ];
401
+ pts [2 ] = xlist [length - 1 ];
402
+ pts [3 ] = ylist [length - 1 ];
403
+ steep_prev =
404
+ fabs (pts_prev [2 ] - pts_prev [0 ]) < fabs (pts_prev [3 ] - pts_prev [1 ]);
405
+ steep_curr = fabs (pts [2 ] - pts [0 ]) < fabs (pts [3 ] - pts [1 ]);
406
+ extra_px = steep_prev != steep_curr ;
407
+ pts_prev [0 ] = pts [0 ];
408
+ pts_prev [1 ] = pts [1 ];
409
+ pts_prev [2 ] = pts [2 ];
410
+ pts_prev [3 ] = pts [3 ];
411
+ if (closed ) {
412
+ draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area , 1 ,
413
+ 1 , extra_px );
353
414
}
415
+ else {
416
+ draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area , 1 ,
417
+ 0 , extra_px );
418
+ }
419
+
354
420
if (closed && length > 2 ) {
355
421
pts [0 ] = xlist [length - 1 ];
356
422
pts [1 ] = ylist [length - 1 ];
357
423
pts [2 ] = xlist [0 ];
358
424
pts [3 ] = ylist [0 ];
359
- draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area );
425
+ steep_prev =
426
+ fabs (pts_prev [2 ] - pts_prev [0 ]) < fabs (pts_prev [3 ] - pts_prev [1 ]);
427
+ steep_curr = fabs (pts [2 ] - pts [0 ]) < fabs (pts [3 ] - pts [1 ]);
428
+ extra_px = steep_prev != steep_curr ;
429
+ draw_aaline (surf , color , pts [0 ], pts [1 ], pts [2 ], pts [3 ], drawn_area , 1 ,
430
+ 1 , extra_px );
360
431
}
361
432
362
433
PyMem_Free (xlist );
@@ -1276,7 +1347,9 @@ set_and_check_rect(SDL_Surface *surf, int x, int y, Uint32 color,
1276
1347
1277
1348
static void
1278
1349
draw_aaline (SDL_Surface * surf , Uint32 color , float from_x , float from_y ,
1279
- float to_x , float to_y , int * drawn_area )
1350
+ float to_x , float to_y , int * drawn_area ,
1351
+ int disable_first_endpoint , int disable_second_endpoint ,
1352
+ int extra_pixel_for_aalines )
1280
1353
{
1281
1354
float gradient , dx , dy , intersect_y , brightness ;
1282
1355
int x , x_pixel_start , x_pixel_end ;
@@ -1379,68 +1452,80 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y,
1379
1452
1380
1453
/* Handle endpoints separately.
1381
1454
* The line is not a mathematical line of thickness zero. The same
1382
- * goes for the endpoints. The have a height and width of one pixel. */
1455
+ * goes for the endpoints. The have a height and width of one pixel.
1456
+ * Extra pixel drawing is requested externally from aalines.
1457
+ * It is drawn only when one line is steep and other is not.*/
1383
1458
/* First endpoint */
1384
- x_pixel_start = (int )from_x ;
1385
- y_endpoint = intersect_y = from_y + gradient * (x_pixel_start - from_x );
1386
- if (to_x > clip_left + 1.0f ) {
1387
- x_gap = 1 + x_pixel_start - from_x ;
1388
- brightness = y_endpoint - (int )y_endpoint ;
1389
- if (steep ) {
1390
- x = (int )y_endpoint ;
1391
- y = x_pixel_start ;
1392
- }
1393
- else {
1394
- x = x_pixel_start ;
1395
- y = (int )y_endpoint ;
1396
- }
1397
- if ((int )y_endpoint < y_endpoint ) {
1459
+ if (!disable_first_endpoint || extra_pixel_for_aalines ) {
1460
+ x_pixel_start = (int )from_x ;
1461
+ y_endpoint = intersect_y =
1462
+ from_y + gradient * (x_pixel_start - from_x );
1463
+ if (to_x > clip_left + 1.0f ) {
1464
+ x_gap = 1 + x_pixel_start - from_x ;
1465
+ brightness = y_endpoint - (int )y_endpoint ;
1466
+ if (steep ) {
1467
+ x = (int )y_endpoint ;
1468
+ y = x_pixel_start ;
1469
+ }
1470
+ else {
1471
+ x = x_pixel_start ;
1472
+ y = (int )y_endpoint ;
1473
+ }
1474
+ if ((int )y_endpoint < y_endpoint ) {
1475
+ pixel_color = get_antialiased_color (surf , x , y , color ,
1476
+ brightness * x_gap );
1477
+ set_and_check_rect (surf , x , y , pixel_color , drawn_area );
1478
+ }
1479
+ if (steep ) {
1480
+ x -- ;
1481
+ }
1482
+ else {
1483
+ y -- ;
1484
+ }
1485
+ brightness = 1 - brightness ;
1398
1486
pixel_color =
1399
1487
get_antialiased_color (surf , x , y , color , brightness * x_gap );
1400
1488
set_and_check_rect (surf , x , y , pixel_color , drawn_area );
1489
+ intersect_y += gradient ;
1490
+ x_pixel_start ++ ;
1401
1491
}
1402
- if (steep ) {
1403
- x -- ;
1404
- }
1405
- else {
1406
- y -- ;
1407
- }
1408
- brightness = 1 - brightness ;
1409
- pixel_color =
1410
- get_antialiased_color (surf , x , y , color , brightness * x_gap );
1411
- set_and_check_rect (surf , x , y , pixel_color , drawn_area );
1412
- intersect_y += gradient ;
1413
- x_pixel_start ++ ;
1492
+ }
1493
+ /* To be sure main loop skips first endpoint.*/
1494
+ if (disable_first_endpoint ) {
1495
+ x_pixel_start = (int )ceil (from_x );
1496
+ intersect_y = from_y + gradient * (x_pixel_start - from_x );
1414
1497
}
1415
1498
/* Second endpoint */
1416
1499
x_pixel_end = (int )ceil (to_x );
1417
- if (from_x < clip_right - 1.0f ) {
1418
- y_endpoint = to_y + gradient * (x_pixel_end - to_x );
1419
- x_gap = 1 - x_pixel_end + to_x ;
1420
- brightness = y_endpoint - (int )y_endpoint ;
1421
- if (steep ) {
1422
- x = (int )y_endpoint ;
1423
- y = x_pixel_end ;
1424
- }
1425
- else {
1426
- x = x_pixel_end ;
1427
- y = (int )y_endpoint ;
1428
- }
1429
- if ((int )y_endpoint < y_endpoint ) {
1500
+ if (!disable_second_endpoint || extra_pixel_for_aalines ) {
1501
+ if (from_x < clip_right - 1.0f ) {
1502
+ y_endpoint = to_y + gradient * (x_pixel_end - to_x );
1503
+ x_gap = 1 - x_pixel_end + to_x ;
1504
+ brightness = y_endpoint - (int )y_endpoint ;
1505
+ if (steep ) {
1506
+ x = (int )y_endpoint ;
1507
+ y = x_pixel_end ;
1508
+ }
1509
+ else {
1510
+ x = x_pixel_end ;
1511
+ y = (int )y_endpoint ;
1512
+ }
1513
+ if ((int )y_endpoint < y_endpoint ) {
1514
+ pixel_color = get_antialiased_color (surf , x , y , color ,
1515
+ brightness * x_gap );
1516
+ set_and_check_rect (surf , x , y , pixel_color , drawn_area );
1517
+ }
1518
+ if (steep ) {
1519
+ x -- ;
1520
+ }
1521
+ else {
1522
+ y -- ;
1523
+ }
1524
+ brightness = 1 - brightness ;
1430
1525
pixel_color =
1431
1526
get_antialiased_color (surf , x , y , color , brightness * x_gap );
1432
1527
set_and_check_rect (surf , x , y , pixel_color , drawn_area );
1433
1528
}
1434
- if (steep ) {
1435
- x -- ;
1436
- }
1437
- else {
1438
- y -- ;
1439
- }
1440
- brightness = 1 - brightness ;
1441
- pixel_color =
1442
- get_antialiased_color (surf , x , y , color , brightness * x_gap );
1443
- set_and_check_rect (surf , x , y , pixel_color , drawn_area );
1444
1529
}
1445
1530
1446
1531
/* main line drawing loop */
0 commit comments