From 21eefb2239b30103ea8f29eb86cf181916787255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josip=20Komljenovi=C4=87?= Date: Tue, 3 Jun 2025 11:36:55 +0200 Subject: [PATCH 1/4] Fix draw halting when using NaN argument --- src_c/draw.c | 114 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 46 deletions(-) diff --git a/src_c/draw.c b/src_c/draw.c index a63aea97cc..a16868fe7b 100644 --- a/src_c/draw.c +++ b/src_c/draw.c @@ -113,6 +113,8 @@ draw_round_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, return NULL; \ } +#define CHECK_NAN(value) value == 0x80000000 + /* Definition of functions that get called in Python */ /* Draws an antialiased line on the given surface. @@ -183,6 +185,10 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs) return pgRect_New4((int)startx, (int)starty, 0, 0); } + if (CHECK_NAN(startx)) { + return pgRect_New4((int)startx, (int)starty, 0, 0); + } + if (!pgSurface_Lock(surfobj)) { return RAISE(PyExc_RuntimeError, "error locking surface"); } @@ -270,6 +276,10 @@ line(PyObject *self, PyObject *arg, PyObject *kwargs) return pgRect_New4(startx, starty, 0, 0); } + if (CHECK_NAN(startx) || CHECK_NAN(starty) || CHECK_NAN(endx) || CHECK_NAN(endy)) { + return pgRect_New4(startx, starty, 0, 0); + } + if (!pgSurface_Lock(surfobj)) { return RAISE(PyExc_RuntimeError, "error locking surface"); } @@ -421,15 +431,17 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) extra_px = steep_prev > steep_curr; disable_endpoints = !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); - if (closed) { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, - disable_endpoints, extra_px); - } - else { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, 0, disable_endpoints, - extra_px); + if (!CHECK_NAN(pts[0])) { + if (closed) { + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], + pts[2], pts[3], drawn_area, disable_endpoints, + disable_endpoints, extra_px); + } + else { + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], + pts[2], pts[3], drawn_area, 0, disable_endpoints, + extra_px); + } } for (loop = 2; loop < length - 1; ++loop) { @@ -440,19 +452,21 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) /* Comparing previous and current line. * If one is steep and other is not, extra pixel must be drawn.*/ - steep_prev = - fabs(pts_prev[2] - pts_prev[0]) < fabs(pts_prev[3] - pts_prev[1]); - steep_curr = fabs(pts[2] - pts[0]) < fabs(pts[3] - pts[1]); - extra_px = steep_prev != steep_curr; - disable_endpoints = - !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); - pts_prev[0] = pts[0]; - pts_prev[1] = pts[1]; - pts_prev[2] = pts[2]; - pts_prev[3] = pts[3]; - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, - disable_endpoints, extra_px); + if (!CHECK_NAN(pts[0])) { + steep_prev = + fabs(pts_prev[2] - pts_prev[0]) < fabs(pts_prev[3] - pts_prev[1]); + steep_curr = fabs(pts[2] - pts[0]) < fabs(pts[3] - pts[1]); + extra_px = steep_prev != steep_curr; + disable_endpoints = + !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); + pts_prev[0] = pts[0]; + pts_prev[1] = pts[1]; + pts_prev[2] = pts[2]; + pts_prev[3] = pts[3]; + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], + pts[2], pts[3], drawn_area, disable_endpoints, + disable_endpoints, extra_px); + } } /* Last line - if open, add endpoint pixels. */ @@ -470,15 +484,17 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) pts_prev[1] = pts[1]; pts_prev[2] = pts[2]; pts_prev[3] = pts[3]; - if (closed) { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, - disable_endpoints, extra_px); - } - else { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, 0, - extra_px); + if (!CHECK_NAN(pts[0])) { + if (closed) { + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], + pts[2], pts[3], drawn_area, disable_endpoints, + disable_endpoints, extra_px); + } + else { + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], + pts[2], pts[3], drawn_area, disable_endpoints, 0, + extra_px); + } } if (closed && length > 2) { @@ -486,15 +502,17 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) pts[1] = ylist[length - 1]; pts[2] = xlist[0]; pts[3] = ylist[0]; - steep_prev = - fabs(pts_prev[2] - pts_prev[0]) < fabs(pts_prev[3] - pts_prev[1]); - steep_curr = fabs(pts[2] - pts[0]) < fabs(pts[3] - pts[1]); - extra_px = steep_prev != steep_curr; - disable_endpoints = - !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, - disable_endpoints, extra_px); + if (!CHECK_NAN(pts[0])) { + steep_prev = + fabs(pts_prev[2] - pts_prev[0]) < fabs(pts_prev[3] - pts_prev[1]); + steep_curr = fabs(pts[2] - pts[0]) < fabs(pts[3] - pts[1]); + extra_px = steep_prev != steep_curr; + disable_endpoints = + !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], + pts[2], pts[3], drawn_area, disable_endpoints, + disable_endpoints, extra_px); + } } PyMem_Free(points_buf); @@ -615,15 +633,19 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) } for (loop = 1; loop < length; ++loop) { - draw_line_width(surf, surf_clip_rect, color, xlist[loop - 1], - ylist[loop - 1], xlist[loop], ylist[loop], width, - drawn_area); + if (!CHECK_NAN(xlist[loop - 1]) || !CHECK_NAN(ylist[loop - 1]) || !CHECK_NAN(xlist[loop]) || !CHECK_NAN(ylist[loop])) { + draw_line_width(surf, surf_clip_rect, color, xlist[loop - 1], + ylist[loop - 1], xlist[loop], ylist[loop], width, + drawn_area); + } } if (closed && length > 2) { - draw_line_width(surf, surf_clip_rect, color, xlist[length - 1], - ylist[length - 1], xlist[0], ylist[0], width, - drawn_area); + if (!CHECK_NAN(xlist[length - 1]) || !CHECK_NAN(ylist[length - 1]) || !CHECK_NAN(xlist[0]) || !CHECK_NAN(ylist[0])) { + draw_line_width(surf, surf_clip_rect, color, xlist[length - 1], + ylist[length - 1], xlist[0], ylist[0], width, + drawn_area); + } } PyMem_Free(xlist); From dcaa37f1e2235913c5e41a28bfd8bc0d7856a1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josip=20Komljenovi=C4=87?= Date: Tue, 3 Jun 2025 11:51:21 +0200 Subject: [PATCH 2/4] Fix draw halting when using NaN argument --- src_c/draw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src_c/draw.c b/src_c/draw.c index a16868fe7b..c65692e64a 100644 --- a/src_c/draw.c +++ b/src_c/draw.c @@ -113,7 +113,7 @@ draw_round_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, return NULL; \ } -#define CHECK_NAN(value) value == 0x80000000 +#define CHECK_NAN(value) (value == 0x80000000) /* Definition of functions that get called in Python */ @@ -633,7 +633,7 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) } for (loop = 1; loop < length; ++loop) { - if (!CHECK_NAN(xlist[loop - 1]) || !CHECK_NAN(ylist[loop - 1]) || !CHECK_NAN(xlist[loop]) || !CHECK_NAN(ylist[loop])) { + if (!CHECK_NAN(xlist[loop - 1]) && !CHECK_NAN(ylist[loop - 1]) && !CHECK_NAN(xlist[loop]) && !CHECK_NAN(ylist[loop])) { draw_line_width(surf, surf_clip_rect, color, xlist[loop - 1], ylist[loop - 1], xlist[loop], ylist[loop], width, drawn_area); @@ -641,7 +641,7 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) } if (closed && length > 2) { - if (!CHECK_NAN(xlist[length - 1]) || !CHECK_NAN(ylist[length - 1]) || !CHECK_NAN(xlist[0]) || !CHECK_NAN(ylist[0])) { + if (!CHECK_NAN(xlist[length - 1]) && !CHECK_NAN(ylist[length - 1]) && !CHECK_NAN(xlist[0]) && !CHECK_NAN(ylist[0])) { draw_line_width(surf, surf_clip_rect, color, xlist[length - 1], ylist[length - 1], xlist[0], ylist[0], width, drawn_area); From de6024c363a35dee30083924c2e786032aea9818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josip=20Komljenovi=C4=87?= Date: Tue, 3 Jun 2025 12:05:29 +0200 Subject: [PATCH 3/4] Fix draw halting when using NaN argument --- src_c/draw.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src_c/draw.c b/src_c/draw.c index c65692e64a..0837159b01 100644 --- a/src_c/draw.c +++ b/src_c/draw.c @@ -276,7 +276,8 @@ line(PyObject *self, PyObject *arg, PyObject *kwargs) return pgRect_New4(startx, starty, 0, 0); } - if (CHECK_NAN(startx) || CHECK_NAN(starty) || CHECK_NAN(endx) || CHECK_NAN(endy)) { + if (CHECK_NAN(startx) || CHECK_NAN(starty) || CHECK_NAN(endx) || + CHECK_NAN(endy)) { return pgRect_New4(startx, starty, 0, 0); } @@ -433,14 +434,14 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); if (!CHECK_NAN(pts[0])) { if (closed) { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], + pts[1], pts[2], pts[3], drawn_area, disable_endpoints, disable_endpoints, extra_px); } else { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, 0, disable_endpoints, - extra_px); + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], + pts[1], pts[2], pts[3], drawn_area, 0, + disable_endpoints, extra_px); } } @@ -453,8 +454,8 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) /* Comparing previous and current line. * If one is steep and other is not, extra pixel must be drawn.*/ if (!CHECK_NAN(pts[0])) { - steep_prev = - fabs(pts_prev[2] - pts_prev[0]) < fabs(pts_prev[3] - pts_prev[1]); + steep_prev = fabs(pts_prev[2] - pts_prev[0]) < + fabs(pts_prev[3] - pts_prev[1]); steep_curr = fabs(pts[2] - pts[0]) < fabs(pts[3] - pts[1]); extra_px = steep_prev != steep_curr; disable_endpoints = @@ -463,8 +464,8 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) pts_prev[1] = pts[1]; pts_prev[2] = pts[2]; pts_prev[3] = pts[3]; - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], + pts[1], pts[2], pts[3], drawn_area, disable_endpoints, disable_endpoints, extra_px); } } @@ -486,14 +487,14 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) pts_prev[3] = pts[3]; if (!CHECK_NAN(pts[0])) { if (closed) { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], + pts[1], pts[2], pts[3], drawn_area, disable_endpoints, disable_endpoints, extra_px); } else { - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, 0, - extra_px); + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], + pts[1], pts[2], pts[3], drawn_area, disable_endpoints, + 0, extra_px); } } @@ -503,14 +504,14 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) pts[2] = xlist[0]; pts[3] = ylist[0]; if (!CHECK_NAN(pts[0])) { - steep_prev = - fabs(pts_prev[2] - pts_prev[0]) < fabs(pts_prev[3] - pts_prev[1]); + steep_prev = fabs(pts_prev[2] - pts_prev[0]) < + fabs(pts_prev[3] - pts_prev[1]); steep_curr = fabs(pts[2] - pts[0]) < fabs(pts[3] - pts[1]); extra_px = steep_prev != steep_curr; disable_endpoints = !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); - draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], pts[1], - pts[2], pts[3], drawn_area, disable_endpoints, + draw_aaline(surf, surf_clip_rect, surf_format, color, pts[0], + pts[1], pts[2], pts[3], drawn_area, disable_endpoints, disable_endpoints, extra_px); } } @@ -633,7 +634,8 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) } for (loop = 1; loop < length; ++loop) { - if (!CHECK_NAN(xlist[loop - 1]) && !CHECK_NAN(ylist[loop - 1]) && !CHECK_NAN(xlist[loop]) && !CHECK_NAN(ylist[loop])) { + if (!CHECK_NAN(xlist[loop - 1]) && !CHECK_NAN(ylist[loop - 1]) && + !CHECK_NAN(xlist[loop]) && !CHECK_NAN(ylist[loop])) { draw_line_width(surf, surf_clip_rect, color, xlist[loop - 1], ylist[loop - 1], xlist[loop], ylist[loop], width, drawn_area); @@ -641,7 +643,8 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) } if (closed && length > 2) { - if (!CHECK_NAN(xlist[length - 1]) && !CHECK_NAN(ylist[length - 1]) && !CHECK_NAN(xlist[0]) && !CHECK_NAN(ylist[0])) { + if (!CHECK_NAN(xlist[length - 1]) && !CHECK_NAN(ylist[length - 1]) && + !CHECK_NAN(xlist[0]) && !CHECK_NAN(ylist[0])) { draw_line_width(surf, surf_clip_rect, color, xlist[length - 1], ylist[length - 1], xlist[0], ylist[0], width, drawn_area); From 22c280d76ba2593be8ebaf8174278e2d4291e301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josip=20Komljenovi=C4=87?= Date: Tue, 3 Jun 2025 12:07:54 +0200 Subject: [PATCH 4/4] Fix draw halting when using NaN argument --- src_c/draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_c/draw.c b/src_c/draw.c index 0837159b01..d2215f644a 100644 --- a/src_c/draw.c +++ b/src_c/draw.c @@ -113,7 +113,7 @@ draw_round_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, return NULL; \ } -#define CHECK_NAN(value) (value == 0x80000000) +#define CHECK_NAN(value) ((unsigned int)value == 0x80000000) /* Definition of functions that get called in Python */