diff --git a/src_c/_pygame.h b/src_c/_pygame.h index 05bf8a5228..1355b60d6d 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -47,6 +47,8 @@ #include #endif +#include "stdbool.h" + #if SDL_VERSION_ATLEAST(3, 0, 0) #define PG_ShowCursor SDL_ShowCursor #define PG_HideCursor SDL_HideCursor @@ -119,6 +121,8 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_INIT_TIMER 0 +#define PG_GetSurfaceClipRect SDL_GetSurfaceClipRect + #else /* ~SDL_VERSION_ATLEAST(3, 0, 0)*/ #define PG_ShowCursor() SDL_ShowCursor(SDL_ENABLE) #define PG_HideCursor() SDL_ShowCursor(SDL_DISABLE) @@ -190,6 +194,12 @@ PG_UnlockMutex(SDL_mutex *mutex) #define PG_SurfaceHasRLE SDL_HasSurfaceRLE +static inline bool +PG_GetSurfaceClipRect(SDL_Surface *surface, SDL_Rect *rect) +{ + *rect = surface->clip_rect; + return true; +} #endif /* DictProxy is useful for event posting with an arbitrary dict. Maintains diff --git a/src_c/draw.c b/src_c/draw.c index ab5e30c76b..58adb1fd16 100644 --- a/src_c/draw.c +++ b/src_c/draw.c @@ -39,65 +39,70 @@ /* Declaration of drawing algorithms */ static void -draw_line_width(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2, - int y2, int width, int *drawn_area); +draw_line_width(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color, + int x1, int y1, int x2, int y2, int width, int *drawn_area); static void -draw_line(SDL_Surface *surf, int x1, int y1, int x2, int y2, Uint32 color, - int *drawn_area); +draw_line(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, int x2, + int y2, Uint32 color, int *drawn_area); void line_width_corners(float from_x, float from_y, float to_x, float to_y, int width, float *x1, float *y1, float *x2, float *y2, float *x3, float *y3, float *x4, float *y4); static void -draw_aaline(SDL_Surface *surf, Uint32 color, float startx, float starty, - float endx, float endy, int *drawn_area, - int disable_first_endpoint, int disable_second_endpoint, - int extra_pixel_for_aalines); +draw_aaline(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color, + float startx, float starty, float endx, float endy, + int *drawn_area, int disable_first_endpoint, + int disable_second_endpoint, int extra_pixel_for_aalines); static void -draw_arc(SDL_Surface *surf, int x_center, int y_center, int radius1, - int radius2, int width, double angle_start, double angle_stop, - Uint32 color, int *drawn_area); +draw_arc(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x_center, + int y_center, int radius1, int radius2, int width, double angle_start, + double angle_stop, Uint32 color, int *drawn_area); static void -draw_circle_bresenham(SDL_Surface *surf, int x0, int y0, int radius, - int thickness, Uint32 color, int *drawn_area); +draw_circle_bresenham(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, int thickness, Uint32 color, + int *drawn_area); static void -draw_circle_bresenham_thin(SDL_Surface *surf, int x0, int y0, int radius, - Uint32 color, int *drawn_area); +draw_circle_bresenham_thin(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, Uint32 color, int *drawn_area); static void -draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius, - int thickness, Uint32 color, int top_right, int top_left, - int bottom_left, int bottom_right, int *drawn_area); +draw_circle_xiaolinwu(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, int thickness, Uint32 color, + int top_right, int top_left, int bottom_left, + int bottom_right, int *drawn_area); static void -draw_circle_xiaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius, - Uint32 color, int top_right, int top_left, - int bottom_left, int bottom_right, int *drawn_area); +draw_circle_xiaolinwu_thin(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, Uint32 color, int top_right, + int top_left, int bottom_left, int bottom_right, + int *drawn_area); static void -draw_circle_filled(SDL_Surface *surf, int x0, int y0, int radius, Uint32 color, - int *drawn_area); +draw_circle_filled(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, int y0, + int radius, Uint32 color, int *drawn_area); static void -draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, - int thickness, Uint32 color, int top_right, int top_left, - int bottom_left, int bottom_right, int *drawn_area); +draw_circle_quadrant(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, int thickness, Uint32 color, + int top_right, int top_left, int bottom_left, + int bottom_right, int *drawn_area); static void -draw_ellipse_filled(SDL_Surface *surf, int x0, int y0, int width, int height, - Uint32 color, int *drawn_area); +draw_ellipse_filled(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, int y0, + int width, int height, Uint32 color, int *drawn_area); static void -draw_ellipse_thickness(SDL_Surface *surf, int x0, int y0, int width, - int height, int thickness, Uint32 color, - int *drawn_area); +draw_ellipse_thickness(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int width, int height, int thickness, + Uint32 color, int *drawn_area); static void -draw_fillpoly(SDL_Surface *surf, int *vx, int *vy, Py_ssize_t n, Uint32 color, - int *drawn_area); +draw_fillpoly(SDL_Surface *surf, SDL_Rect surf_clip_rect, int *vx, int *vy, + Py_ssize_t n, Uint32 color, int *drawn_area); static int -draw_filltri(SDL_Surface *surf, int *xlist, int *ylist, Uint32 color, - int *drawn_area); +draw_filltri(SDL_Surface *surf, SDL_Rect surf_clip_rect, int *xlist, + int *ylist, Uint32 color, int *drawn_area); static void -draw_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int width, - Uint32 color); +draw_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, int x2, + int y2, int width, Uint32 color); static void -draw_round_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int radius, - int width, Uint32 color, int top_left, int top_right, - int bottom_left, int bottom_right, int *drawn_area); +draw_round_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, + int x2, int y2, int radius, int width, Uint32 color, + int top_left, int top_right, int bottom_left, int bottom_right, + int *drawn_area); // validation of a draw color #define CHECK_LOAD_COLOR(colorobj) \ @@ -152,6 +157,11 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (!pg_TwoFloatsFromObj(start, &startx, &starty)) { @@ -174,14 +184,16 @@ aaline(PyObject *self, PyObject *arg, PyObject *kwargs) float x1, y1, x2, y2, x3, y3, x4, y4; line_width_corners(startx, starty, endx, endy, width, &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4); - draw_line_width(surf, color, (int)startx, (int)starty, (int)endx, - (int)endy, width, drawn_area); - draw_aaline(surf, color, x1, y1, x2, y2, drawn_area, 0, 0, 0); - draw_aaline(surf, color, x3, y3, x4, y4, drawn_area, 0, 0, 0); + draw_line_width(surf, surf_clip_rect, color, (int)startx, (int)starty, + (int)endx, (int)endy, width, drawn_area); + draw_aaline(surf, surf_clip_rect, color, x1, y1, x2, y2, drawn_area, 0, + 0, 0); + draw_aaline(surf, surf_clip_rect, color, x3, y3, x4, y4, drawn_area, 0, + 0, 0); } else { - draw_aaline(surf, color, startx, starty, endx, endy, drawn_area, 0, 0, - 0); + draw_aaline(surf, surf_clip_rect, color, startx, starty, endx, endy, + drawn_area, 0, 0, 0); } if (!pgSurface_Unlock(surfobj)) { @@ -230,6 +242,11 @@ line(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (!pg_TwoIntsFromObj(start, &startx, &starty)) { @@ -248,8 +265,8 @@ line(PyObject *self, PyObject *arg, PyObject *kwargs) return RAISE(PyExc_RuntimeError, "error locking surface"); } - draw_line_width(surf, color, startx, starty, endx, endy, width, - drawn_area); + draw_line_width(surf, surf_clip_rect, color, startx, starty, endx, endy, + width, drawn_area); if (!pgSurface_Unlock(surfobj)) { return RAISE(PyExc_RuntimeError, "error unlocking surface"); @@ -318,6 +335,11 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (!PySequence_Check(points)) { @@ -384,12 +406,13 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) disable_endpoints = !((roundf(pts[2]) == pts[2]) && (roundf(pts[3]) == pts[3])); if (closed) { - draw_aaline(surf, color, pts[0], pts[1], pts[2], pts[3], drawn_area, - disable_endpoints, disable_endpoints, extra_px); + draw_aaline(surf, surf_clip_rect, color, pts[0], pts[1], pts[2], + pts[3], drawn_area, disable_endpoints, disable_endpoints, + extra_px); } else { - draw_aaline(surf, color, pts[0], pts[1], pts[2], pts[3], drawn_area, 0, - disable_endpoints, extra_px); + draw_aaline(surf, surf_clip_rect, color, pts[0], pts[1], pts[2], + pts[3], drawn_area, 0, disable_endpoints, extra_px); } for (loop = 2; loop < length - 1; ++loop) { @@ -410,8 +433,9 @@ 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, color, pts[0], pts[1], pts[2], pts[3], drawn_area, - disable_endpoints, disable_endpoints, extra_px); + draw_aaline(surf, surf_clip_rect, color, pts[0], pts[1], pts[2], + pts[3], drawn_area, disable_endpoints, disable_endpoints, + extra_px); } /* Last line - if open, add endpoint pixels. */ @@ -430,12 +454,13 @@ aalines(PyObject *self, PyObject *arg, PyObject *kwargs) pts_prev[2] = pts[2]; pts_prev[3] = pts[3]; if (closed) { - draw_aaline(surf, color, pts[0], pts[1], pts[2], pts[3], drawn_area, - disable_endpoints, disable_endpoints, extra_px); + draw_aaline(surf, surf_clip_rect, color, pts[0], pts[1], pts[2], + pts[3], drawn_area, disable_endpoints, disable_endpoints, + extra_px); } else { - draw_aaline(surf, color, pts[0], pts[1], pts[2], pts[3], drawn_area, - disable_endpoints, 0, extra_px); + draw_aaline(surf, surf_clip_rect, color, pts[0], pts[1], pts[2], + pts[3], drawn_area, disable_endpoints, 0, extra_px); } if (closed && length > 2) { @@ -449,8 +474,9 @@ 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])); - draw_aaline(surf, color, pts[0], pts[1], pts[2], pts[3], drawn_area, - disable_endpoints, disable_endpoints, extra_px); + draw_aaline(surf, surf_clip_rect, color, pts[0], pts[1], pts[2], + pts[3], drawn_area, disable_endpoints, disable_endpoints, + extra_px); } PyMem_Free(points_buf); @@ -505,6 +531,11 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (!PySequence_Check(points)) { @@ -564,13 +595,15 @@ lines(PyObject *self, PyObject *arg, PyObject *kwargs) } for (loop = 1; loop < length; ++loop) { - draw_line_width(surf, color, xlist[loop - 1], ylist[loop - 1], - xlist[loop], ylist[loop], width, drawn_area); + 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, color, xlist[length - 1], ylist[length - 1], - xlist[0], ylist[0], width, drawn_area); + draw_line_width(surf, surf_clip_rect, color, xlist[length - 1], + ylist[length - 1], xlist[0], ylist[0], width, + drawn_area); } PyMem_Free(xlist); @@ -626,6 +659,11 @@ arc(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (width < 0) { @@ -647,8 +685,9 @@ arc(PyObject *self, PyObject *arg, PyObject *kwargs) width = MIN(width, MIN(rect->w, rect->h) / 2); - draw_arc(surf, rect->x + rect->w / 2, rect->y + rect->h / 2, rect->w / 2, - rect->h / 2, width, angle_start, angle_stop, color, drawn_area); + draw_arc(surf, surf_clip_rect, rect->x + rect->w / 2, + rect->y + rect->h / 2, rect->w / 2, rect->h / 2, width, + angle_start, angle_stop, color, drawn_area); if (!pgSurface_Unlock(surfobj)) { return RAISE(PyExc_RuntimeError, "error unlocking surface"); @@ -698,6 +737,11 @@ ellipse(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (width < 0) { @@ -710,12 +754,12 @@ ellipse(PyObject *self, PyObject *arg, PyObject *kwargs) if (!width || width >= MIN(rect->w / 2 + rect->w % 2, rect->h / 2 + rect->h % 2)) { - draw_ellipse_filled(surf, rect->x, rect->y, rect->w, rect->h, color, - drawn_area); + draw_ellipse_filled(surf, surf_clip_rect, rect->x, rect->y, rect->w, + rect->h, color, drawn_area); } else { - draw_ellipse_thickness(surf, rect->x, rect->y, rect->w, rect->h, - width - 1, color, drawn_area); + draw_ellipse_thickness(surf, surf_clip_rect, rect->x, rect->y, rect->w, + rect->h, width - 1, color, drawn_area); } if (!pgSurface_Unlock(surfobj)) { @@ -738,7 +782,6 @@ circle(PyObject *self, PyObject *args, PyObject *kwargs) PyObject *colorobj; SDL_Surface *surf = NULL; Uint32 color; - SDL_Rect cliprect; PyObject *posobj, *radiusobj; int posx, posy, radius; int width = 0; /* Default values. */ @@ -782,6 +825,11 @@ circle(PyObject *self, PyObject *args, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (radius < 1 || width < 0) { @@ -792,12 +840,10 @@ circle(PyObject *self, PyObject *args, PyObject *kwargs) width = radius; } - SDL_GetClipRect(surf, &cliprect); - - if (posx > cliprect.x + cliprect.w + radius || - posx < cliprect.x - radius || - posy > cliprect.y + cliprect.h + radius || - posy < cliprect.y - radius) { + if (posx > surf_clip_rect.x + surf_clip_rect.w + radius || + posx < surf_clip_rect.x - radius || + posy > surf_clip_rect.y + surf_clip_rect.h + radius || + posy < surf_clip_rect.y - radius) { return pgRect_New4(posx, posy, 0, 0); } @@ -808,20 +854,22 @@ circle(PyObject *self, PyObject *args, PyObject *kwargs) if ((top_right == 0 && top_left == 0 && bottom_left == 0 && bottom_right == 0)) { if (!width || width == radius) { - draw_circle_filled(surf, posx, posy, radius, color, drawn_area); + draw_circle_filled(surf, surf_clip_rect, posx, posy, radius, color, + drawn_area); } else if (width == 1) { - draw_circle_bresenham_thin(surf, posx, posy, radius, color, - drawn_area); + draw_circle_bresenham_thin(surf, surf_clip_rect, posx, posy, + radius, color, drawn_area); } else { - draw_circle_bresenham(surf, posx, posy, radius, width, color, - drawn_area); + draw_circle_bresenham(surf, surf_clip_rect, posx, posy, radius, + width, color, drawn_area); } } else { - draw_circle_quadrant(surf, posx, posy, radius, width, color, top_right, - top_left, bottom_left, bottom_right, drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, posx, posy, radius, width, + color, top_right, top_left, bottom_left, + bottom_right, drawn_area); } if (!pgSurface_Unlock(surfobj)) { @@ -843,7 +891,6 @@ aacircle(PyObject *self, PyObject *args, PyObject *kwargs) PyObject *colorobj; SDL_Surface *surf = NULL; Uint32 color; - SDL_Rect cliprect; PyObject *posobj, *radiusobj; int posx, posy, radius; int width = 0; /* Default values. */ @@ -885,6 +932,11 @@ aacircle(PyObject *self, PyObject *args, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (radius < 1 || width < 0) { @@ -895,12 +947,10 @@ aacircle(PyObject *self, PyObject *args, PyObject *kwargs) width = radius; } - SDL_GetClipRect(surf, &cliprect); - - if (posx > cliprect.x + cliprect.w + radius || - posx < cliprect.x - radius || - posy > cliprect.y + cliprect.h + radius || - posy < cliprect.y - radius) { + if (posx > surf_clip_rect.x + surf_clip_rect.w + radius || + posx < surf_clip_rect.x - radius || + posy > surf_clip_rect.y + surf_clip_rect.h + radius || + posy < surf_clip_rect.y - radius) { return pgRect_New4(posx, posy, 0, 0); } @@ -911,35 +961,35 @@ aacircle(PyObject *self, PyObject *args, PyObject *kwargs) if ((top_right == 0 && top_left == 0 && bottom_left == 0 && bottom_right == 0)) { if (!width || width == radius) { - draw_circle_filled(surf, posx, posy, radius - 1, color, - drawn_area); - draw_circle_xiaolinwu(surf, posx, posy, radius, 2, color, 1, 1, 1, - 1, drawn_area); + draw_circle_filled(surf, surf_clip_rect, posx, posy, radius - 1, + color, drawn_area); + draw_circle_xiaolinwu(surf, surf_clip_rect, posx, posy, radius, 2, + color, 1, 1, 1, 1, drawn_area); } else if (width == 1) { - draw_circle_xiaolinwu_thin(surf, posx, posy, radius, color, 1, 1, - 1, 1, drawn_area); + draw_circle_xiaolinwu_thin(surf, surf_clip_rect, posx, posy, + radius, color, 1, 1, 1, 1, drawn_area); } else { - draw_circle_xiaolinwu(surf, posx, posy, radius, width, color, 1, 1, - 1, 1, drawn_area); + draw_circle_xiaolinwu(surf, surf_clip_rect, posx, posy, radius, + width, color, 1, 1, 1, 1, drawn_area); } } else { if (!width || width == radius) { - draw_circle_xiaolinwu(surf, posx, posy, radius, radius, color, - top_right, top_left, bottom_left, - bottom_right, drawn_area); + draw_circle_xiaolinwu(surf, surf_clip_rect, posx, posy, radius, + radius, color, top_right, top_left, + bottom_left, bottom_right, drawn_area); } else if (width == 1) { - draw_circle_xiaolinwu_thin(surf, posx, posy, radius, color, - top_right, top_left, bottom_left, - bottom_right, drawn_area); + draw_circle_xiaolinwu_thin(surf, surf_clip_rect, posx, posy, + radius, color, top_right, top_left, + bottom_left, bottom_right, drawn_area); } else { - draw_circle_xiaolinwu(surf, posx, posy, radius, width, color, - top_right, top_left, bottom_left, - bottom_right, drawn_area); + draw_circle_xiaolinwu(surf, surf_clip_rect, posx, posy, radius, + width, color, top_right, top_left, + bottom_left, bottom_right, drawn_area); } } @@ -998,6 +1048,11 @@ polygon(PyObject *self, PyObject *arg, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (!PySequence_Check(points)) { @@ -1046,10 +1101,11 @@ polygon(PyObject *self, PyObject *arg, PyObject *kwargs) } if (length != 3) { - draw_fillpoly(surf, xlist, ylist, length, color, drawn_area); + draw_fillpoly(surf, surf_clip_rect, xlist, ylist, length, color, + drawn_area); } else { - draw_filltri(surf, xlist, ylist, color, drawn_area); + draw_filltri(surf, surf_clip_rect, xlist, ylist, color, drawn_area); } PyMem_Free(points_buf); @@ -1078,7 +1134,6 @@ rect(PyObject *self, PyObject *args, PyObject *kwargs) int top_left_radius = -1, top_right_radius = -1, bottom_left_radius = -1, bottom_right_radius = -1; SDL_Rect sdlrect; - SDL_Rect cliprect; int result; SDL_Rect clipped; int drawn_area[4] = {INT_MAX, INT_MAX, INT_MIN, @@ -1113,6 +1168,11 @@ rect(PyObject *self, PyObject *args, PyObject *kwargs) PG_SURF_BytesPerPixel(surf)); } + SDL_Rect surf_clip_rect; + if (!PG_GetSurfaceClipRect(surf, &surf_clip_rect)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + CHECK_LOAD_COLOR(colorobj) if (width < 0) { @@ -1130,16 +1190,16 @@ rect(PyObject *self, PyObject *args, PyObject *kwargs) sdlrect.y = rect->y; sdlrect.w = rect->w; sdlrect.h = rect->h; - SDL_GetClipRect(surf, &cliprect); /* SDL_FillRect respects the clip rect already, but in order to return the drawn area, we need to do this here, and keep the pointer to the result in clipped */ - if (!SDL_IntersectRect(&sdlrect, &cliprect, &clipped)) { + if (!SDL_IntersectRect(&sdlrect, &surf_clip_rect, &clipped)) { return pgRect_New4(rect->x, rect->y, 0, 0); } if (width > 0 && (width * 2) < clipped.w && (width * 2) < clipped.h) { - draw_rect(surf, sdlrect.x, sdlrect.y, sdlrect.x + sdlrect.w - 1, - sdlrect.y + sdlrect.h - 1, width, color); + draw_rect(surf, surf_clip_rect, sdlrect.x, sdlrect.y, + sdlrect.x + sdlrect.w - 1, sdlrect.y + sdlrect.h - 1, + width, color); } else { pgSurface_Prep(surfobj); @@ -1172,10 +1232,10 @@ rect(PyObject *self, PyObject *args, PyObject *kwargs) width = MAX(rect->w / 2, rect->h / 2); } - draw_round_rect(surf, rect->x, rect->y, rect->x + rect->w - 1, - rect->y + rect->h - 1, radius, width, color, - top_left_radius, top_right_radius, bottom_left_radius, - bottom_right_radius, drawn_area); + draw_round_rect(surf, surf_clip_rect, rect->x, rect->y, + rect->x + rect->w - 1, rect->y + rect->h - 1, radius, + width, color, top_left_radius, top_right_radius, + bottom_left_radius, bottom_right_radius, drawn_area); if (!pgSurface_Unlock(surfobj)) { return RAISE(PyExc_RuntimeError, "error unlocking surface"); } @@ -1207,14 +1267,14 @@ compare_int(const void *a, const void *b) } static Uint32 -get_antialiased_color(SDL_Surface *surf, int x, int y, Uint32 original_color, - float brightness) +get_antialiased_color(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x, int y, + Uint32 original_color, float brightness) { Uint8 color_part[4], background_color[4]; SDL_GetRGBA(original_color, surf->format, &color_part[0], &color_part[1], &color_part[2], &color_part[3]); - if (x < surf->clip_rect.x || x >= surf->clip_rect.x + surf->clip_rect.w || - y < surf->clip_rect.y || y >= surf->clip_rect.y + surf->clip_rect.h) + if (x < surf_clip_rect.x || x >= surf_clip_rect.x + surf_clip_rect.w || + y < surf_clip_rect.y || y >= surf_clip_rect.y + surf_clip_rect.h) return original_color; Uint32 pixel = 0; @@ -1295,8 +1355,8 @@ add_line_to_drawn_list(int x1, int y1, int x2, int y2, int *pts) } static int -clip_line(SDL_Surface *surf, int *x1, int *y1, int *x2, int *y2, int width, - int xinc) +clip_line(SDL_Surface *surf, SDL_Rect surf_clip_rect, int *x1, int *y1, + int *x2, int *y2, int width, int xinc) { int left, right, top, bottom; if (xinc) { @@ -1311,9 +1371,9 @@ clip_line(SDL_Surface *surf, int *x1, int *y1, int *x2, int *y2, int width, top = MIN(*y1, *y2) - width; bottom = MAX(*y1, *y2) + width; } - if (surf->clip_rect.x > right || surf->clip_rect.y > bottom || - surf->clip_rect.x + surf->clip_rect.w <= left || - surf->clip_rect.y + surf->clip_rect.h <= top) { + if (surf_clip_rect.x > right || surf_clip_rect.y > bottom || + surf_clip_rect.x + surf_clip_rect.w <= left || + surf_clip_rect.y + surf_clip_rect.h <= top) { return 0; } @@ -1321,13 +1381,13 @@ clip_line(SDL_Surface *surf, int *x1, int *y1, int *x2, int *y2, int width, } static int -set_at(SDL_Surface *surf, int x, int y, Uint32 color) +set_at(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x, int y, Uint32 color) { SDL_PixelFormat *format = surf->format; Uint8 *pixels = (Uint8 *)surf->pixels; - if (x < surf->clip_rect.x || x >= surf->clip_rect.x + surf->clip_rect.w || - y < surf->clip_rect.y || y >= surf->clip_rect.y + surf->clip_rect.h) + if (x < surf_clip_rect.x || x >= surf_clip_rect.x + surf_clip_rect.w || + y < surf_clip_rect.y || y >= surf_clip_rect.y + surf_clip_rect.h) return 0; switch (PG_FORMAT_BytesPerPixel(format)) { @@ -1352,18 +1412,18 @@ set_at(SDL_Surface *surf, int x, int y, Uint32 color) } static void -set_and_check_rect(SDL_Surface *surf, int x, int y, Uint32 color, - int *drawn_area) +set_and_check_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x, int y, + Uint32 color, int *drawn_area) { - if (set_at(surf, x, y, color)) + if (set_at(surf, surf_clip_rect, x, y, color)) add_pixel_to_drawn_list(x, y, drawn_area); } static void -draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, - float to_x, float to_y, int *drawn_area, - int disable_first_endpoint, int disable_second_endpoint, - int extra_pixel_for_aalines) +draw_aaline(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color, + float from_x, float from_y, float to_x, float to_y, + int *drawn_area, int disable_first_endpoint, + int disable_second_endpoint, int extra_pixel_for_aalines) { float gradient, dx, dy, intersect_y, brightness; int x, x_pixel_start, x_pixel_end; @@ -1377,10 +1437,10 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, /* Single point. * A line with length 0 is drawn as a single pixel at full brightness. */ if (fabs(dx) < 0.0001 && fabs(dy) < 0.0001) { - pixel_color = - get_antialiased_color(surf, (int)floor(from_x + 0.5), - (int)floor(from_y + 0.5), color, 1); - set_and_check_rect(surf, (int)floor(from_x + 0.5), + pixel_color = get_antialiased_color( + surf, surf_clip_rect, (int)floor(from_x + 0.5), + (int)floor(from_y + 0.5), color, 1); + set_and_check_rect(surf, surf_clip_rect, (int)floor(from_x + 0.5), (int)floor(from_y + 0.5), pixel_color, drawn_area); return; } @@ -1388,10 +1448,10 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, /* To draw correctly the pixels at the border of the clipping area when * the line crosses it, we need to clip it one pixel wider in all four * directions: */ - clip_left = (float)surf->clip_rect.x - 1.0f; - clip_right = (float)clip_left + surf->clip_rect.w + 1.0f; - clip_top = (float)surf->clip_rect.y - 1.0f; - clip_bottom = (float)clip_top + surf->clip_rect.h + 1.0f; + clip_left = (float)surf_clip_rect.x - 1.0f; + clip_right = (float)clip_left + surf_clip_rect.w + 1.0f; + clip_top = (float)surf_clip_rect.y - 1.0f; + clip_bottom = (float)clip_top + surf_clip_rect.h + 1.0f; steep = fabs(dx) < fabs(dy); if (steep) { @@ -1486,9 +1546,10 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, y = (int)y_endpoint; } if ((int)y_endpoint < y_endpoint) { - pixel_color = get_antialiased_color(surf, x, y, color, - brightness * x_gap); - set_and_check_rect(surf, x, y, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x, y, + color, brightness * x_gap); + set_and_check_rect(surf, surf_clip_rect, x, y, pixel_color, + drawn_area); } if (steep) { x--; @@ -1497,9 +1558,10 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, y--; } brightness = 1 - brightness; - pixel_color = - get_antialiased_color(surf, x, y, color, brightness * x_gap); - set_and_check_rect(surf, x, y, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x, y, + color, brightness * x_gap); + set_and_check_rect(surf, surf_clip_rect, x, y, pixel_color, + drawn_area); intersect_y += gradient; x_pixel_start++; } @@ -1525,9 +1587,10 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, y = (int)y_endpoint; } if ((int)y_endpoint < y_endpoint) { - pixel_color = get_antialiased_color(surf, x, y, color, - brightness * x_gap); - set_and_check_rect(surf, x, y, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x, y, + color, brightness * x_gap); + set_and_check_rect(surf, surf_clip_rect, x, y, pixel_color, + drawn_area); } if (steep) { x--; @@ -1536,9 +1599,10 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, y--; } brightness = 1 - brightness; - pixel_color = - get_antialiased_color(surf, x, y, color, brightness * x_gap); - set_and_check_rect(surf, x, y, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x, y, + color, brightness * x_gap); + set_and_check_rect(surf, surf_clip_rect, x, y, pixel_color, + drawn_area); } } @@ -1547,26 +1611,30 @@ draw_aaline(SDL_Surface *surf, Uint32 color, float from_x, float from_y, y = (int)intersect_y; if (steep) { brightness = 1 - intersect_y + y; - pixel_color = - get_antialiased_color(surf, y - 1, x, color, brightness); - set_and_check_rect(surf, y - 1, x, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, y - 1, x, + color, brightness); + set_and_check_rect(surf, surf_clip_rect, y - 1, x, pixel_color, + drawn_area); if (y < intersect_y) { brightness = 1 - brightness; - pixel_color = - get_antialiased_color(surf, y, x, color, brightness); - set_and_check_rect(surf, y, x, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, y, x, + color, brightness); + set_and_check_rect(surf, surf_clip_rect, y, x, pixel_color, + drawn_area); } } else { brightness = 1 - intersect_y + y; - pixel_color = - get_antialiased_color(surf, x, y - 1, color, brightness); - set_and_check_rect(surf, x, y - 1, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x, y - 1, + color, brightness); + set_and_check_rect(surf, surf_clip_rect, x, y - 1, pixel_color, + drawn_area); if (y < intersect_y) { brightness = 1 - brightness; - pixel_color = - get_antialiased_color(surf, x, y, color, brightness); - set_and_check_rect(surf, x, y, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x, y, + color, brightness); + set_and_check_rect(surf, surf_clip_rect, x, y, pixel_color, + drawn_area); } } intersect_y += gradient; @@ -1645,9 +1713,10 @@ drawvertline(SDL_Surface *surf, Uint32 color, int y1, int x1, int y2) } static void -drawhorzlineclip(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2) +drawhorzlineclip(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color, + int x1, int y1, int x2) { - if (y1 < surf->clip_rect.y || y1 >= surf->clip_rect.y + surf->clip_rect.h) + if (y1 < surf_clip_rect.y || y1 >= surf_clip_rect.y + surf_clip_rect.h) return; if (x2 < x1) { @@ -1656,24 +1725,24 @@ drawhorzlineclip(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2) x2 = temp; } - x1 = MAX(x1, surf->clip_rect.x); - x2 = MIN(x2, surf->clip_rect.x + surf->clip_rect.w - 1); + x1 = MAX(x1, surf_clip_rect.x); + x2 = MIN(x2, surf_clip_rect.x + surf_clip_rect.w - 1); - if (x2 < surf->clip_rect.x || x1 >= surf->clip_rect.x + surf->clip_rect.w) + if (x2 < surf_clip_rect.x || x1 >= surf_clip_rect.x + surf_clip_rect.w) return; if (x1 == x2) { - set_at(surf, x1, y1, color); + set_at(surf, surf_clip_rect, x1, y1, color); return; } drawhorzline(surf, color, x1, y1, x2); } static void -drawhorzlineclipbounding(SDL_Surface *surf, Uint32 color, int x1, int y1, - int x2, int *pts) +drawhorzlineclipbounding(SDL_Surface *surf, SDL_Rect surf_clip_rect, + Uint32 color, int x1, int y1, int x2, int *pts) { - if (y1 < surf->clip_rect.y || y1 >= surf->clip_rect.y + surf->clip_rect.h) + if (y1 < surf_clip_rect.y || y1 >= surf_clip_rect.y + surf_clip_rect.h) return; if (x2 < x1) { @@ -1682,14 +1751,14 @@ drawhorzlineclipbounding(SDL_Surface *surf, Uint32 color, int x1, int y1, x2 = temp; } - x1 = MAX(x1, surf->clip_rect.x); - x2 = MIN(x2, surf->clip_rect.x + surf->clip_rect.w - 1); + x1 = MAX(x1, surf_clip_rect.x); + x2 = MIN(x2, surf_clip_rect.x + surf_clip_rect.w - 1); - if (x2 < surf->clip_rect.x || x1 >= surf->clip_rect.x + surf->clip_rect.w) + if (x2 < surf_clip_rect.x || x1 >= surf_clip_rect.x + surf_clip_rect.w) return; if (x1 == x2) { - set_and_check_rect(surf, x1, y1, color, pts); + set_and_check_rect(surf, surf_clip_rect, x1, y1, color, pts); return; } @@ -1711,8 +1780,8 @@ swap_coordinates(int *x1, int *y1, int *x2, int *y2) } static int -draw_filltri(SDL_Surface *surf, int *xlist, int *ylist, Uint32 color, - int *draw_area) +draw_filltri(SDL_Surface *surf, SDL_Rect surf_clip_rect, int *xlist, + int *ylist, Uint32 color, int *draw_area) { int p0x, p0y, p1x, p1y, p2x, p2y; @@ -1752,26 +1821,27 @@ draw_filltri(SDL_Surface *surf, int *xlist, int *ylist, Uint32 color, else x2 = p1x + (int)((y - p1y) * d3); - drawhorzlineclipbounding(surf, color, x1, y, x2, draw_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x1, y, x2, + draw_area); } return 0; } static void -draw_line_width(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2, - int y2, int width, int *drawn_area) +draw_line_width(SDL_Surface *surf, SDL_Rect surf_clip_rect, Uint32 color, + int x1, int y1, int x2, int y2, int width, int *drawn_area) { int dx, dy, err, e2, sx, sy, start_draw, end_draw; - int end_x = surf->clip_rect.x + surf->clip_rect.w - 1; - int end_y = surf->clip_rect.y + surf->clip_rect.h - 1; + int end_x = surf_clip_rect.x + surf_clip_rect.w - 1; + int end_y = surf_clip_rect.y + surf_clip_rect.h - 1; int xinc = 0; int extra_width = 1 - (width % 2); if (width < 1) return; if (width == 1) { - draw_line(surf, x1, y1, x2, y2, color, drawn_area); + draw_line(surf, surf_clip_rect, x1, y1, x2, y2, color, drawn_area); return; } @@ -1784,11 +1854,11 @@ draw_line_width(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2, xinc = 1; } - if (!clip_line(surf, &x1, &y1, &x2, &y2, width, xinc)) + if (!clip_line(surf, surf_clip_rect, &x1, &y1, &x2, &y2, width, xinc)) return; if (x1 == x2 && y1 == y2) { /* Single point */ - start_draw = MAX((x1 - width) + extra_width, surf->clip_rect.x); + start_draw = MAX((x1 - width) + extra_width, surf_clip_rect.x); end_draw = MIN(end_x, x1 + width); if (start_draw <= end_draw) { drawhorzline(surf, color, start_draw, y1, end_draw); @@ -1804,9 +1874,8 @@ draw_line_width(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2, err = (dx > dy ? dx : -dy) / 2; if (xinc) { while (y1 != (y2 + sy)) { - if (surf->clip_rect.y <= y1 && y1 <= end_y) { - start_draw = - MAX((x1 - width) + extra_width, surf->clip_rect.x); + if (surf_clip_rect.y <= y1 && y1 <= end_y) { + start_draw = MAX((x1 - width) + extra_width, surf_clip_rect.x); end_draw = MIN(end_x, x1 + width); if (start_draw <= end_draw) { drawhorzline(surf, color, start_draw, y1, end_draw); @@ -1827,9 +1896,8 @@ draw_line_width(SDL_Surface *surf, Uint32 color, int x1, int y1, int x2, } else { while (x1 != (x2 + sx)) { - if (surf->clip_rect.x <= x1 && x1 <= end_x) { - start_draw = - MAX((y1 - width) + extra_width, surf->clip_rect.y); + if (surf_clip_rect.x <= x1 && x1 <= end_x) { + start_draw = MAX((y1 - width) + extra_width, surf_clip_rect.y); end_draw = MIN(end_y, y1 + width); if (start_draw <= end_draw) { drawvertline(surf, color, start_draw, x1, end_draw); @@ -1887,18 +1955,19 @@ line_width_corners(float from_x, float from_y, float to_x, float to_y, * https://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm */ static void -draw_line(SDL_Surface *surf, int x1, int y1, int x2, int y2, Uint32 color, - int *drawn_area) +draw_line(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, int x2, + int y2, Uint32 color, int *drawn_area) { int dx, dy, err, e2, sx, sy; if (x1 == x2 && y1 == y2) { /* Single point */ - set_and_check_rect(surf, x1, y1, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x1, y1, color, drawn_area); return; } if (y1 == y2) { /* Horizontal line */ dx = (x1 < x2) ? 1 : -1; for (sx = 0; sx <= abs(x1 - x2); sx++) { - set_and_check_rect(surf, x1 + dx * sx, y1, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x1 + dx * sx, y1, color, + drawn_area); } return; @@ -1906,14 +1975,15 @@ draw_line(SDL_Surface *surf, int x1, int y1, int x2, int y2, Uint32 color, if (x1 == x2) { /* Vertical line */ dy = (y1 < y2) ? 1 : -1; for (sy = 0; sy <= abs(y1 - y2); sy++) - set_and_check_rect(surf, x1, y1 + dy * sy, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x1, y1 + dy * sy, color, + drawn_area); return; } dx = abs(x2 - x1), sx = x1 < x2 ? 1 : -1; dy = abs(y2 - y1), sy = y1 < y2 ? 1 : -1; err = (dx > dy ? dx : -dy) / 2; while (x1 != x2 || y1 != y2) { - set_and_check_rect(surf, x1, y1, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x1, y1, color, drawn_area); e2 = err; if (e2 > -dx) { err -= dy; @@ -1924,7 +1994,7 @@ draw_line(SDL_Surface *surf, int x1, int y1, int x2, int y2, Uint32 color, y1 += sy; } } - set_and_check_rect(surf, x2, y2, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x2, y2, color, drawn_area); } static int @@ -1979,13 +2049,13 @@ unsafe_set_at(SDL_Surface *surf, int x, int y, Uint32 color) } static void -calc_arc_bounds(SDL_Surface *surf, double angle_start, double angle_stop, - int radius1, int radius2, int inner_radius1, int inner_radius2, - double invsqr_radius1, double invsqr_radius2, - double invsqr_inner_radius1, double invsqr_inner_radius2, - double min_dotproduct, double x_middle, double y_middle, - int x_center, int y_center, int *minxbound, int *minybound, - int *maxxbound, int *maxybound) +calc_arc_bounds(SDL_Surface *surf, SDL_Rect surf_clip_rect, double angle_start, + double angle_stop, int radius1, int radius2, int inner_radius1, + int inner_radius2, double invsqr_radius1, + double invsqr_radius2, double invsqr_inner_radius1, + double invsqr_inner_radius2, double min_dotproduct, + double x_middle, double y_middle, int x_center, int y_center, + int *minxbound, int *minybound, int *maxxbound, int *maxybound) { // calculate bounding box // these values find the corners of the arc @@ -2012,25 +2082,25 @@ calc_arc_bounds(SDL_Surface *surf, double angle_start, double angle_stop, if (-x_middle < min_dotproduct) minx = MIN(MIN(x_start_inner, x_stop_inner), MIN(x_start_outer, x_stop_outer)); - minx = MAX(minx, surf->clip_rect.x - x_center); + minx = MAX(minx, surf_clip_rect.x - x_center); int miny = -radius2; if (-y_middle < min_dotproduct) miny = MIN(MIN(y_start_inner, y_stop_inner), MIN(y_start_outer, y_stop_outer)); - miny = MAX(miny, surf->clip_rect.y - y_center); + miny = MAX(miny, surf_clip_rect.y - y_center); int maxx = radius1; if (x_middle < min_dotproduct) maxx = MAX(MAX(x_start_inner, x_stop_inner), MAX(x_start_outer, x_stop_outer)); - maxx = MIN(maxx, surf->clip_rect.x + surf->clip_rect.w - x_center - 1); + maxx = MIN(maxx, surf_clip_rect.x + surf_clip_rect.w - x_center - 1); int maxy = radius2; if (y_middle < min_dotproduct) maxy = MAX(MAX(y_start_inner, y_stop_inner), MAX(y_start_outer, y_stop_outer)); - maxy = MIN(maxy, surf->clip_rect.y + surf->clip_rect.h - y_center - 1); + maxy = MIN(maxy, surf_clip_rect.y + surf_clip_rect.h - y_center - 1); // Early return to avoid setting drawn_area with possibly strange values if (minx >= maxx || miny >= maxy) @@ -2124,9 +2194,9 @@ calc_arc_bounds(SDL_Surface *surf, double angle_start, double angle_stop, } static void -draw_arc(SDL_Surface *surf, int x_center, int y_center, int radius1, - int radius2, int width, double angle_start, double angle_stop, - Uint32 color, int *drawn_area) +draw_arc(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x_center, + int y_center, int radius1, int radius2, int width, double angle_start, + double angle_stop, Uint32 color, int *drawn_area) { // handle cases from documentation if (width <= 0) @@ -2167,8 +2237,8 @@ draw_arc(SDL_Surface *surf, int x_center, int y_center, int radius1, int miny = 0; int maxx = -1; int maxy = -1; - calc_arc_bounds(surf, angle_start, angle_stop, radius1, radius2, - inner_radius1, inner_radius2, invsqr_radius1, + calc_arc_bounds(surf, surf_clip_rect, angle_start, angle_stop, radius1, + radius2, inner_radius1, inner_radius2, invsqr_radius1, invsqr_radius2, invsqr_inner_radius1, invsqr_inner_radius2, min_dotproduct, x_middle, y_middle, x_center, y_center, &minx, &miny, &maxx, &maxy); @@ -2250,8 +2320,9 @@ draw_arc(SDL_Surface *surf, int x_center, int y_center, int radius1, * with additional line width parameter */ static void -draw_circle_bresenham(SDL_Surface *surf, int x0, int y0, int radius, - int thickness, Uint32 color, int *drawn_area) +draw_circle_bresenham(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, int thickness, Uint32 color, + int *drawn_area) { long long x = 0; long long y = radius; @@ -2279,22 +2350,26 @@ draw_circle_bresenham(SDL_Surface *surf, int x0, int y0, int radius, d1 += dx + radius_squared; } if (line) { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 + (int)x - 1, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 + (int)y - 1, - x0 + (int)x - 1, drawn_area); - } - else { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 + (int)y - 1, - x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x_inner - 1, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 - (int)y, x0 + (int)x - 1, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x_inner - 1, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 + (int)y - 1, x0 + (int)x - 1, drawn_area); } + else { + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 - (int)x_inner, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 + (int)y - 1, x0 - (int)x_inner, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x_inner - 1, y0 - (int)y, + x0 + (int)x - 1, drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x_inner - 1, y0 + (int)y - 1, + x0 + (int)x - 1, drawn_area); + } x++; y--; dx += double_radius_squared; @@ -2319,22 +2394,26 @@ draw_circle_bresenham(SDL_Surface *surf, int x0, int y0, int radius, ((x + 0.5) * (x + 0.5) + (y - 1) * (y - 1) - radius_squared); while (y >= 0) { if (line) { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 + (int)x - 1, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 + (int)y - 1, - x0 + (int)x - 1, drawn_area); - } - else { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 + (int)y - 1, - x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x_inner - 1, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 - (int)y, x0 + (int)x - 1, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x_inner - 1, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 + (int)y - 1, x0 + (int)x - 1, drawn_area); } + else { + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 - (int)x_inner, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 + (int)y - 1, x0 - (int)x_inner, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x_inner - 1, y0 - (int)y, + x0 + (int)x - 1, drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x_inner - 1, y0 + (int)y - 1, + x0 + (int)x - 1, drawn_area); + } if (d1 > 0) { y--; dy -= double_radius_squared; @@ -2386,8 +2465,8 @@ draw_circle_bresenham(SDL_Surface *surf, int x0, int y0, int radius, } static void -draw_circle_bresenham_thin(SDL_Surface *surf, int x0, int y0, int radius, - Uint32 color, int *drawn_area) +draw_circle_bresenham_thin(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, Uint32 color, int *drawn_area) { int f = 1 - radius; int ddF_x = 0; @@ -2405,27 +2484,30 @@ draw_circle_bresenham_thin(SDL_Surface *surf, int x0, int y0, int radius, ddF_x += 2; f += ddF_x + 1; - set_and_check_rect(surf, x0 + x - 1, y0 + y - 1, color, + set_and_check_rect(surf, surf_clip_rect, x0 + x - 1, y0 + y - 1, color, drawn_area); /* 7 */ - set_and_check_rect(surf, x0 - x, y0 + y - 1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - x, y0 + y - 1, color, drawn_area); /* 6 */ - set_and_check_rect(surf, x0 + x - 1, y0 - y, color, - drawn_area); /* 2 */ - set_and_check_rect(surf, x0 - x, y0 - y, color, drawn_area); /* 3 */ - set_and_check_rect(surf, x0 + y - 1, y0 + x - 1, color, + set_and_check_rect(surf, surf_clip_rect, x0 + x - 1, y0 - y, color, + drawn_area); /* 2 */ + set_and_check_rect(surf, surf_clip_rect, x0 - x, y0 - y, color, + drawn_area); /* 3 */ + set_and_check_rect(surf, surf_clip_rect, x0 + y - 1, y0 + x - 1, color, drawn_area); /* 8 */ - set_and_check_rect(surf, x0 + y - 1, y0 - x, color, + set_and_check_rect(surf, surf_clip_rect, x0 + y - 1, y0 - x, color, drawn_area); /* 1 */ - set_and_check_rect(surf, x0 - y, y0 + x - 1, color, - drawn_area); /* 5 */ - set_and_check_rect(surf, x0 - y, y0 - x, color, drawn_area); /* 4 */ + set_and_check_rect(surf, surf_clip_rect, x0 - y, y0 + x - 1, color, + drawn_area); /* 5 */ + set_and_check_rect(surf, surf_clip_rect, x0 - y, y0 - x, color, + drawn_area); /* 4 */ } } static void -draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, - int thickness, Uint32 color, int top_right, int top_left, - int bottom_left, int bottom_right, int *drawn_area) +draw_circle_quadrant(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, int thickness, Uint32 color, + int top_right, int top_left, int bottom_left, + int bottom_right, int *drawn_area) { int f = 1 - radius; int ddF_x = 0; @@ -2440,13 +2522,17 @@ draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, int i; if (radius == 1) { if (top_right > 0) - set_and_check_rect(surf, x0, y0 - 1, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x0, y0 - 1, color, + drawn_area); if (top_left > 0) - set_and_check_rect(surf, x0 - 1, y0 - 1, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x0 - 1, y0 - 1, color, + drawn_area); if (bottom_left > 0) - set_and_check_rect(surf, x0 - 1, y0, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x0 - 1, y0, color, + drawn_area); if (bottom_right > 0) - set_and_check_rect(surf, x0, y0, color, drawn_area); + set_and_check_rect(surf, surf_clip_rect, x0, y0, color, + drawn_area); return; } @@ -2478,32 +2564,34 @@ draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, for (i = 0; i < thickness; i++) { y1 = y - i; if ((y0 - y1) < (y0 - x)) - set_and_check_rect(surf, x0 + x - 1, y0 - y1, color, - drawn_area); /* 2 */ + set_and_check_rect(surf, surf_clip_rect, x0 + x - 1, + y0 - y1, color, drawn_area); /* 2 */ if ((x0 + y1 - 1) >= (x0 + x - 1)) - set_and_check_rect(surf, x0 + y1 - 1, y0 - x, color, - drawn_area); /* 1 */ + set_and_check_rect(surf, surf_clip_rect, x0 + y1 - 1, + y0 - x, color, drawn_area); /* 1 */ } } if (top_left > 0) { for (i = 0; i < thickness; i++) { y1 = y - i; if ((y0 - y1) <= (y0 - x)) - set_and_check_rect(surf, x0 - x, y0 - y1, color, - drawn_area); /* 3 */ + set_and_check_rect(surf, surf_clip_rect, x0 - x, + y0 - y1, color, drawn_area); /* 3 */ if ((x0 - y1) < (x0 - x)) - set_and_check_rect(surf, x0 - y1, y0 - x, color, - drawn_area); /* 4 */ + set_and_check_rect(surf, surf_clip_rect, x0 - y1, + y0 - x, color, drawn_area); /* 4 */ } } if (bottom_left > 0) { for (i = 0; i < thickness; i++) { y1 = y - i; if ((x0 - y1) <= (x0 - x)) - set_and_check_rect(surf, x0 - y1, y0 + x - 1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - y1, + y0 + x - 1, color, drawn_area); /* 5 */ if ((y0 + y1 - 1) > (y0 + x - 1)) - set_and_check_rect(surf, x0 - x, y0 + y1 - 1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - x, + y0 + y1 - 1, color, drawn_area); /* 6 */ } } @@ -2511,11 +2599,13 @@ draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, for (i = 0; i < thickness; i++) { y1 = y - i; if ((y0 + y1 - 1) >= (y0 + x - 1)) - set_and_check_rect(surf, x0 + x - 1, y0 + y1 - 1, - color, drawn_area); /* 7 */ + set_and_check_rect(surf, surf_clip_rect, x0 + x - 1, + y0 + y1 - 1, color, + drawn_area); /* 7 */ if ((x0 + y1 - 1) > (x0 + x - 1)) - set_and_check_rect(surf, x0 + y1 - 1, y0 + x - 1, - color, drawn_area); /* 8 */ + set_and_check_rect(surf, surf_clip_rect, x0 + y1 - 1, + y0 + x - 1, color, + drawn_area); /* 8 */ } } } @@ -2532,42 +2622,42 @@ draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, f += ddF_x + 1; if (top_right > 0) { for (y1 = y0 - x; y1 <= y0; y1++) { - set_and_check_rect(surf, x0 + y - 1, y1, color, - drawn_area); /* 1 */ + set_and_check_rect(surf, surf_clip_rect, x0 + y - 1, y1, + color, drawn_area); /* 1 */ } for (y1 = y0 - y; y1 <= y0; y1++) { - set_and_check_rect(surf, x0 + x - 1, y1, color, - drawn_area); /* 2 */ + set_and_check_rect(surf, surf_clip_rect, x0 + x - 1, y1, + color, drawn_area); /* 2 */ } } if (top_left > 0) { for (y1 = y0 - x; y1 <= y0; y1++) { - set_and_check_rect(surf, x0 - y, y1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - y, y1, color, drawn_area); /* 4 */ } for (y1 = y0 - y; y1 <= y0; y1++) { - set_and_check_rect(surf, x0 - x, y1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - x, y1, color, drawn_area); /* 3 */ } } if (bottom_left > 0) { for (y1 = y0; y1 < y0 + x; y1++) { - set_and_check_rect(surf, x0 - y, y1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - y, y1, color, drawn_area); /* 4 */ } for (y1 = y0; y1 < y0 + y; y1++) { - set_and_check_rect(surf, x0 - x, y1, color, + set_and_check_rect(surf, surf_clip_rect, x0 - x, y1, color, drawn_area); /* 3 */ } } if (bottom_right > 0) { for (y1 = y0; y1 < y0 + x; y1++) { - set_and_check_rect(surf, x0 + y - 1, y1, color, - drawn_area); /* 1 */ + set_and_check_rect(surf, surf_clip_rect, x0 + y - 1, y1, + color, drawn_area); /* 1 */ } for (y1 = y0; y1 < y0 + y; y1++) { - set_and_check_rect(surf, x0 + x - 1, y1, color, - drawn_area); /* 2 */ + set_and_check_rect(surf, surf_clip_rect, x0 + x - 1, y1, + color, drawn_area); /* 2 */ } } } @@ -2575,8 +2665,8 @@ draw_circle_quadrant(SDL_Surface *surf, int x0, int y0, int radius, } static void -draw_circle_filled(SDL_Surface *surf, int x0, int y0, int radius, Uint32 color, - int *drawn_area) +draw_circle_filled(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, int y0, + int radius, Uint32 color, int *drawn_area) { int f = 1 - radius; int ddF_x = 0; @@ -2605,57 +2695,68 @@ draw_circle_filled(SDL_Surface *surf, int x0, int y0, int radius, Uint32 color, /* optimisation to avoid overdrawing and repeated return rect checks: only draw a line if y-step is about to be decreased. */ if (f >= 0) { - drawhorzlineclipbounding(surf, color, x0 - x, y0 + y - 1, - x0 + MIN(x - 1, xmax), drawn_area); - drawhorzlineclipbounding(surf, color, x0 - x, y0 - y, - x0 + MIN(x - 1, xmax), drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - x, + y0 + y - 1, x0 + MIN(x - 1, xmax), + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - x, + y0 - y, x0 + MIN(x - 1, xmax), + drawn_area); } - drawhorzlineclipbounding(surf, color, x0 - y, y0 + x - 1, - x0 + MIN(y - 1, xmax), drawn_area); - drawhorzlineclipbounding(surf, color, x0 - y, y0 - x, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - y, + y0 + x - 1, x0 + MIN(y - 1, xmax), + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - y, y0 - x, x0 + MIN(y - 1, xmax), drawn_area); } } static void -draw_eight_symetric_pixels(SDL_Surface *surf, int x0, int y0, Uint32 color, - int x, int y, float opacity, int top_right, - int top_left, int bottom_left, int bottom_right, - int *drawn_area) +draw_eight_symetric_pixels(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, Uint32 color, int x, int y, float opacity, + int top_right, int top_left, int bottom_left, + int bottom_right, int *drawn_area) { opacity = opacity / 255.0f; Uint32 pixel_color; if (top_right == 1) { - pixel_color = - get_antialiased_color(surf, x0 + x, y0 - y, color, opacity); - set_and_check_rect(surf, x0 + x, y0 - y, pixel_color, drawn_area); - pixel_color = - get_antialiased_color(surf, x0 + y, y0 - x, color, opacity); - set_and_check_rect(surf, x0 + y, y0 - x, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 + x, + y0 - y, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 + x, y0 - y, pixel_color, + drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 + y, + y0 - x, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 + y, y0 - x, pixel_color, + drawn_area); } if (top_left == 1) { - pixel_color = - get_antialiased_color(surf, x0 - x, y0 - y, color, opacity); - set_and_check_rect(surf, x0 - x, y0 - y, pixel_color, drawn_area); - pixel_color = - get_antialiased_color(surf, x0 - y, y0 - x, color, opacity); - set_and_check_rect(surf, x0 - y, y0 - x, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 - x, + y0 - y, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 - x, y0 - y, pixel_color, + drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 - y, + y0 - x, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 - y, y0 - x, pixel_color, + drawn_area); } if (bottom_left == 1) { - pixel_color = - get_antialiased_color(surf, x0 - x, y0 + y, color, opacity); - set_and_check_rect(surf, x0 - x, y0 + y, pixel_color, drawn_area); - pixel_color = - get_antialiased_color(surf, x0 - y, y0 + x, color, opacity); - set_and_check_rect(surf, x0 - y, y0 + x, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 - x, + y0 + y, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 - x, y0 + y, pixel_color, + drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 - y, + y0 + x, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 - y, y0 + x, pixel_color, + drawn_area); } if (bottom_right == 1) { - pixel_color = - get_antialiased_color(surf, x0 + x, y0 + y, color, opacity); - set_and_check_rect(surf, x0 + x, y0 + y, pixel_color, drawn_area); - pixel_color = - get_antialiased_color(surf, x0 + y, y0 + x, color, opacity); - set_and_check_rect(surf, x0 + y, y0 + x, pixel_color, drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 + x, + y0 + y, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 + x, y0 + y, pixel_color, + drawn_area); + pixel_color = get_antialiased_color(surf, surf_clip_rect, x0 + y, + y0 + x, color, opacity); + set_and_check_rect(surf, surf_clip_rect, x0 + y, y0 + x, pixel_color, + drawn_area); } } @@ -2664,9 +2765,10 @@ draw_eight_symetric_pixels(SDL_Surface *surf, int x0, int y0, Uint32 color, * with additional line width parameter and quadrants option */ static void -draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius, - int thickness, Uint32 color, int top_right, int top_left, - int bottom_left, int bottom_right, int *drawn_area) +draw_circle_xiaolinwu(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, int thickness, Uint32 color, + int top_right, int top_left, int bottom_left, + int bottom_right, int *drawn_area) { for (int layer_radius = radius - thickness; layer_radius <= radius; layer_radius++) { @@ -2682,12 +2784,14 @@ draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius, --y; } prev_opacity = opacity; - draw_eight_symetric_pixels(surf, x0, y0, color, x, y, 255.0f, - top_right, top_left, bottom_left, - bottom_right, drawn_area); - draw_eight_symetric_pixels( - surf, x0, y0, color, x, y - 1, (float)opacity, top_right, - top_left, bottom_left, bottom_right, drawn_area); + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, + x, y, 255.0f, top_right, top_left, + bottom_left, bottom_right, + drawn_area); + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, + x, y - 1, (float)opacity, top_right, + top_left, bottom_left, bottom_right, + drawn_area); ++x; } } @@ -2699,13 +2803,14 @@ draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius, --y; } prev_opacity = opacity; - draw_eight_symetric_pixels(surf, x0, y0, color, x, y, - 255.0f - (float)opacity, top_right, + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, + x, y, 255.0f - (float)opacity, + top_right, top_left, bottom_left, + bottom_right, drawn_area); + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, + x, y - 1, 255.0f, top_right, top_left, bottom_left, bottom_right, drawn_area); - draw_eight_symetric_pixels( - surf, x0, y0, color, x, y - 1, 255.0f, top_right, top_left, - bottom_left, bottom_right, drawn_area); ++x; } } @@ -2717,12 +2822,14 @@ draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius, --y; } prev_opacity = opacity; - draw_eight_symetric_pixels(surf, x0, y0, color, x, y, 255.0f, - top_right, top_left, bottom_left, - bottom_right, drawn_area); - draw_eight_symetric_pixels( - surf, x0, y0, color, x, y - 1, 255.0f, top_right, top_left, - bottom_left, bottom_right, drawn_area); + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, + x, y, 255.0f, top_right, top_left, + bottom_left, bottom_right, + drawn_area); + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, + x, y - 1, 255.0f, top_right, + top_left, bottom_left, bottom_right, + drawn_area); ++x; } } @@ -2730,9 +2837,10 @@ draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius, } static void -draw_circle_xiaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius, - Uint32 color, int top_right, int top_left, - int bottom_left, int bottom_right, int *drawn_area) +draw_circle_xiaolinwu_thin(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int radius, Uint32 color, int top_right, + int top_left, int bottom_left, int bottom_right, + int *drawn_area) { int x = 0; int y = radius; @@ -2746,29 +2854,30 @@ draw_circle_xiaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius, } prev_opacity = opacity; draw_eight_symetric_pixels( - surf, x0, y0, color, x, y, 255.0f - (float)opacity, top_right, - top_left, bottom_left, bottom_right, drawn_area); - draw_eight_symetric_pixels(surf, x0, y0, color, x, y - 1, - (float)opacity, top_right, top_left, + surf, surf_clip_rect, x0, y0, color, x, y, 255.0f - (float)opacity, + top_right, top_left, bottom_left, bottom_right, drawn_area); + draw_eight_symetric_pixels(surf, surf_clip_rect, x0, y0, color, x, + y - 1, (float)opacity, top_right, top_left, bottom_left, bottom_right, drawn_area); ++x; } } static void -draw_ellipse_filled(SDL_Surface *surf, int x0, int y0, int width, int height, - Uint32 color, int *drawn_area) +draw_ellipse_filled(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, int y0, + int width, int height, Uint32 color, int *drawn_area) { long long dx, dy, x, y; int x_offset, y_offset; double d1, d2; if (width == 1) { - draw_line(surf, x0, y0, x0, y0 + height - 1, color, drawn_area); + draw_line(surf, surf_clip_rect, x0, y0, x0, y0 + height - 1, color, + drawn_area); return; } if (height == 1) { - drawhorzlineclipbounding(surf, color, x0, y0, x0 + width - 1, - drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0, y0, + x0 + width - 1, drawn_area); return; } x0 = x0 + width / 2; @@ -2783,9 +2892,10 @@ draw_ellipse_filled(SDL_Surface *surf, int x0, int y0, int width, int height, dx = 2 * height * height * x; dy = 2 * width * width * y; while (dx < dy) { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 + (int)x - x_offset, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 + (int)x - x_offset, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 + (int)y - y_offset, x0 + (int)x - x_offset, drawn_area); if (d1 < 0) { @@ -2805,9 +2915,10 @@ draw_ellipse_filled(SDL_Surface *surf, int x0, int y0, int width, int height, (((double)width * width) * ((y - 1) * (y - 1))) - ((double)width * width * height * height); while (y >= 0) { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 + (int)x - x_offset, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 + (int)x - x_offset, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 + (int)y - y_offset, x0 + (int)x - x_offset, drawn_area); if (d2 > 0) { @@ -2826,9 +2937,9 @@ draw_ellipse_filled(SDL_Surface *surf, int x0, int y0, int width, int height, } static void -draw_ellipse_thickness(SDL_Surface *surf, int x0, int y0, int width, - int height, int thickness, Uint32 color, - int *drawn_area) +draw_ellipse_thickness(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x0, + int y0, int width, int height, int thickness, + Uint32 color, int *drawn_area) { long long dx, dy, dx_inner, dy_inner, x, y, x_inner, y_inner; int line, x_offset, y_offset; @@ -2855,22 +2966,25 @@ draw_ellipse_thickness(SDL_Surface *surf, int x0, int y0, int width, dy_inner = 2 * (width - thickness) * (width - thickness) * y_inner; while (dx < dy) { if (line) { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 + (int)x - x_offset, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 + (int)x - x_offset, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 + (int)y - y_offset, x0 + (int)x - x_offset, drawn_area); } else { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, - y0 + (int)y - y_offset, x0 - (int)x_inner, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x - x_offset, - y0 - (int)y, x0 + (int)x_inner - x_offset, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 + (int)y - y_offset, x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x - x_offset, + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x - x_offset, y0 - (int)y, + x0 + (int)x_inner - x_offset, drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x - x_offset, y0 + (int)y - y_offset, x0 + (int)x_inner - x_offset, drawn_area); } @@ -2915,22 +3029,25 @@ draw_ellipse_thickness(SDL_Surface *surf, int x0, int y0, int width, ((double)width * width * height * height); while (y >= 0) { if (line) { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 + (int)x - x_offset, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 + (int)x - x_offset, + drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, y0 + (int)y - y_offset, x0 + (int)x - x_offset, drawn_area); } else { - drawhorzlineclipbounding(surf, color, x0 - (int)x, y0 - (int)y, - x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 - (int)x, - y0 + (int)y - y_offset, x0 - (int)x_inner, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 - (int)y, x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x - x_offset, - y0 - (int)y, x0 + (int)x_inner - x_offset, + drawhorzlineclipbounding(surf, surf_clip_rect, color, x0 - (int)x, + y0 + (int)y - y_offset, x0 - (int)x_inner, drawn_area); - drawhorzlineclipbounding(surf, color, x0 + (int)x - x_offset, + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x - x_offset, y0 - (int)y, + x0 + (int)x_inner - x_offset, drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x0 + (int)x - x_offset, y0 + (int)y - y_offset, x0 + (int)x_inner - x_offset, drawn_area); } @@ -3002,8 +3119,9 @@ draw_ellipse_thickness(SDL_Surface *surf, int x0, int y0, int width, } static void -draw_fillpoly(SDL_Surface *surf, int *point_x, int *point_y, - Py_ssize_t num_points, Uint32 color, int *drawn_area) +draw_fillpoly(SDL_Surface *surf, SDL_Rect surf_clip_rect, int *point_x, + int *point_y, Py_ssize_t num_points, Uint32 color, + int *drawn_area) { /* point_x : x coordinates of the points * point-y : the y coordinates of the points @@ -3040,7 +3158,8 @@ draw_fillpoly(SDL_Surface *surf, int *point_x, int *point_y, minx = MIN(minx, point_x[i]); maxx = MAX(maxx, point_x[i]); } - drawhorzlineclipbounding(surf, color, minx, miny, maxx, drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, minx, miny, maxx, + drawn_area); PyMem_Free(x_intersect); return; } @@ -3090,8 +3209,9 @@ draw_fillpoly(SDL_Surface *surf, int *point_x, int *point_y, } qsort(x_intersect, n_intersections, sizeof(int), compare_int); for (i = 0; (i < n_intersections); i += 2) { - drawhorzlineclipbounding(surf, color, x_intersect[i], y, - x_intersect[i + 1], drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, + x_intersect[i], y, x_intersect[i + 1], + drawn_area); } } @@ -3109,32 +3229,35 @@ draw_fillpoly(SDL_Surface *surf, int *point_x, int *point_y, y = point_y[i]; if ((miny < y) && (point_y[i_previous] == y) && (y < maxy)) { - drawhorzlineclipbounding(surf, color, point_x[i], y, - point_x[i_previous], drawn_area); + drawhorzlineclipbounding(surf, surf_clip_rect, color, point_x[i], + y, point_x[i_previous], drawn_area); } } PyMem_Free(x_intersect); } static void -draw_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int width, - Uint32 color) +draw_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, int x2, + int y2, int width, Uint32 color) { int i; for (i = 0; i < width; i++) { - drawhorzlineclip(surf, color, x1, y1 + i, x2); - drawhorzlineclip(surf, color, x1, y2 - i, x2); + drawhorzlineclip(surf, surf_clip_rect, color, x1, y1 + i, x2); + drawhorzlineclip(surf, surf_clip_rect, color, x1, y2 - i, x2); } for (i = 0; i < (y2 - y1) - 2 * width + 1; i++) { - drawhorzlineclip(surf, color, x1, y1 + width + i, x1 + width - 1); - drawhorzlineclip(surf, color, x2 - width + 1, y1 + width + i, x2); + drawhorzlineclip(surf, surf_clip_rect, color, x1, y1 + width + i, + x1 + width - 1); + drawhorzlineclip(surf, surf_clip_rect, color, x2 - width + 1, + y1 + width + i, x2); } } static void -draw_round_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int radius, - int width, Uint32 color, int top_left, int top_right, - int bottom_left, int bottom_right, int *drawn_area) +draw_round_rect(SDL_Surface *surf, SDL_Rect surf_clip_rect, int x1, int y1, + int x2, int y2, int radius, int width, Uint32 color, + int top_left, int top_right, int bottom_left, int bottom_right, + int *drawn_area) { int pts[16], i; float q_top, q_left, q_bottom, q_right, f; @@ -3177,14 +3300,18 @@ draw_round_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int radius, pts[13] = y2; pts[14] = y2; pts[15] = y2 - bottom_left; - draw_fillpoly(surf, pts, pts + 8, 8, color, drawn_area); - draw_circle_quadrant(surf, x2 - top_right + 1, y1 + top_right, - top_right, 0, color, 1, 0, 0, 0, drawn_area); - draw_circle_quadrant(surf, x1 + top_left, y1 + top_left, top_left, 0, - color, 0, 1, 0, 0, drawn_area); - draw_circle_quadrant(surf, x1 + bottom_left, y2 - bottom_left + 1, - bottom_left, 0, color, 0, 0, 1, 0, drawn_area); - draw_circle_quadrant(surf, x2 - bottom_right + 1, + draw_fillpoly(surf, surf_clip_rect, pts, pts + 8, 8, color, + drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, x2 - top_right + 1, + y1 + top_right, top_right, 0, color, 1, 0, 0, 0, + drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, x1 + top_left, + y1 + top_left, top_left, 0, color, 0, 1, 0, 0, + drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, x1 + bottom_left, + y2 - bottom_left + 1, bottom_left, 0, color, 0, 0, + 1, 0, drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, x2 - bottom_right + 1, y2 - bottom_right + 1, bottom_right, 0, color, 0, 0, 0, 1, drawn_area); } @@ -3192,12 +3319,12 @@ draw_round_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int radius, if (x2 - top_right == x1 + top_left) { for (i = 0; i < width; i++) { set_and_check_rect( - surf, x1 + top_left, y1 + i, color, + surf, surf_clip_rect, x1 + top_left, y1 + i, color, drawn_area); /* Fill gap if reduced radius */ } } else - draw_line_width(surf, color, x1 + top_left, + draw_line_width(surf, surf_clip_rect, color, x1 + top_left, y1 + (int)(width / 2) - 1 + width % 2, x2 - top_right, y1 + (int)(width / 2) - 1 + width % 2, width, @@ -3205,47 +3332,51 @@ draw_round_rect(SDL_Surface *surf, int x1, int y1, int x2, int y2, int radius, if (y2 - bottom_left == y1 + top_left) { for (i = 0; i < width; i++) { set_and_check_rect( - surf, x1 + i, y1 + top_left, color, + surf, surf_clip_rect, x1 + i, y1 + top_left, color, drawn_area); /* Fill gap if reduced radius */ } } else draw_line_width( - surf, color, x1 + (int)(width / 2) - 1 + width % 2, - y1 + top_left, x1 + (int)(width / 2) - 1 + width % 2, - y2 - bottom_left, width, drawn_area); /* Left line */ + surf, surf_clip_rect, color, + x1 + (int)(width / 2) - 1 + width % 2, y1 + top_left, + x1 + (int)(width / 2) - 1 + width % 2, y2 - bottom_left, width, + drawn_area); /* Left line */ if (x2 - bottom_right == x1 + bottom_left) { for (i = 0; i < width; i++) { set_and_check_rect( - surf, x1 + bottom_left, y2 - i, color, + surf, surf_clip_rect, x1 + bottom_left, y2 - i, color, drawn_area); /* Fill gap if reduced radius */ } } else - draw_line_width(surf, color, x1 + bottom_left, + draw_line_width(surf, surf_clip_rect, color, x1 + bottom_left, y2 - (int)(width / 2), x2 - bottom_right, y2 - (int)(width / 2), width, drawn_area); /* Bottom line */ if (y2 - bottom_right == y1 + top_right) { for (i = 0; i < width; i++) { set_and_check_rect( - surf, x2 - i, y1 + top_right, color, + surf, surf_clip_rect, x2 - i, y1 + top_right, color, drawn_area); /* Fill gap if reduced radius */ } } else - draw_line_width(surf, color, x2 - (int)(width / 2), y1 + top_right, - x2 - (int)(width / 2), y2 - bottom_right, width, + draw_line_width(surf, surf_clip_rect, color, x2 - (int)(width / 2), + y1 + top_right, x2 - (int)(width / 2), + y2 - bottom_right, width, drawn_area); /* Right line */ - draw_circle_quadrant(surf, x2 - top_right + 1, y1 + top_right, - top_right, width, color, 1, 0, 0, 0, drawn_area); - draw_circle_quadrant(surf, x1 + top_left, y1 + top_left, top_left, - width, color, 0, 1, 0, 0, drawn_area); - draw_circle_quadrant(surf, x1 + bottom_left, y2 - bottom_left + 1, - bottom_left, width, color, 0, 0, 1, 0, + draw_circle_quadrant(surf, surf_clip_rect, x2 - top_right + 1, + y1 + top_right, top_right, width, color, 1, 0, 0, + 0, drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, x1 + top_left, + y1 + top_left, top_left, width, color, 0, 1, 0, 0, drawn_area); - draw_circle_quadrant(surf, x2 - bottom_right + 1, + draw_circle_quadrant(surf, surf_clip_rect, x1 + bottom_left, + y2 - bottom_left + 1, bottom_left, width, color, + 0, 0, 1, 0, drawn_area); + draw_circle_quadrant(surf, surf_clip_rect, x2 - bottom_right + 1, y2 - bottom_right + 1, bottom_right, width, color, 0, 0, 0, 1, drawn_area); }