render: Add floating point versions of various draw APIs.

This commit is contained in:
Ryan C. Gordon 2018-10-23 01:34:03 -04:00
parent cad0a2f730
commit 8340b0f0e2
6 changed files with 643 additions and 76 deletions

View File

@ -40,7 +40,7 @@ extern "C" {
#endif #endif
/** /**
* \brief The structure that defines a point * \brief The structure that defines a point (integer)
* *
* \sa SDL_EnclosePoints * \sa SDL_EnclosePoints
* \sa SDL_PointInRect * \sa SDL_PointInRect
@ -52,7 +52,20 @@ typedef struct SDL_Point
} SDL_Point; } SDL_Point;
/** /**
* \brief A rectangle, with the origin at the upper left. * \brief The structure that defines a point (floating point)
*
* \sa SDL_EnclosePoints
* \sa SDL_PointInRect
*/
typedef struct SDL_FPoint
{
float x;
float y;
} SDL_FPoint;
/**
* \brief A rectangle, with the origin at the upper left (integer).
* *
* \sa SDL_RectEmpty * \sa SDL_RectEmpty
* \sa SDL_RectEquals * \sa SDL_RectEquals
@ -67,6 +80,19 @@ typedef struct SDL_Rect
int w, h; int w, h;
} SDL_Rect; } SDL_Rect;
/**
* \brief A rectangle, with the origin at the upper left (floating point).
*/
typedef struct SDL_FRect
{
float x;
float y;
float w;
float h;
} SDL_FRect;
/** /**
* \brief Returns true if point resides inside a rectangle. * \brief Returns true if point resides inside a rectangle.
*/ */

View File

@ -835,6 +835,148 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
const SDL_Point *center, const SDL_Point *center,
const SDL_RendererFlip flip); const SDL_RendererFlip flip);
/**
* \brief Draw a point on the current rendering target.
*
* \param renderer The renderer which should draw a point.
* \param x The x coordinate of the point.
* \param y The y coordinate of the point.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer,
float x, float y);
/**
* \brief Draw multiple points on the current rendering target.
*
* \param renderer The renderer which should draw multiple points.
* \param points The points to draw
* \param count The number of points to draw
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer,
const SDL_FPoint * points,
int count);
/**
* \brief Draw a line on the current rendering target.
*
* \param renderer The renderer which should draw a line.
* \param x1 The x coordinate of the start point.
* \param y1 The y coordinate of the start point.
* \param x2 The x coordinate of the end point.
* \param y2 The y coordinate of the end point.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer,
float x1, float y1, float x2, float y2);
/**
* \brief Draw a series of connected lines on the current rendering target.
*
* \param renderer The renderer which should draw multiple lines.
* \param points The points along the lines
* \param count The number of points, drawing count-1 lines
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer,
const SDL_FPoint * points,
int count);
/**
* \brief Draw a rectangle on the current rendering target.
*
* \param renderer The renderer which should draw a rectangle.
* \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer,
const SDL_FRect * rect);
/**
* \brief Draw some number of rectangles on the current rendering target.
*
* \param renderer The renderer which should draw multiple rectangles.
* \param rects A pointer to an array of destination rectangles.
* \param count The number of rectangles.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects,
int count);
/**
* \brief Fill a rectangle on the current rendering target with the drawing color.
*
* \param renderer The renderer which should fill a rectangle.
* \param rect A pointer to the destination rectangle, or NULL for the entire
* rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer,
const SDL_FRect * rect);
/**
* \brief Fill some number of rectangles on the current rendering target with the drawing color.
*
* \param renderer The renderer which should fill multiple rectangles.
* \param rects A pointer to an array of destination rectangles.
* \param count The number of rectangles.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects,
int count);
/**
* \brief Copy a portion of the texture to the current rendering target.
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_FRect * dstrect);
/**
* \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
* \param angle An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction
* \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2).
* \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_FRect * dstrect,
const double angle,
const SDL_FPoint *center,
const SDL_RendererFlip flip);
/** /**
* \brief Read pixels from the current rendering target. * \brief Read pixels from the current rendering target.
* *

View File

@ -697,3 +697,13 @@
#define SDL_IsTablet SDL_IsTablet_REAL #define SDL_IsTablet SDL_IsTablet_REAL
#define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_REAL #define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_REAL
#define SDL_RenderFlush SDL_RenderFlush_REAL #define SDL_RenderFlush SDL_RenderFlush_REAL
#define SDL_RenderDrawPointF SDL_RenderDrawPointF_REAL
#define SDL_RenderDrawPointsF SDL_RenderDrawPointsF_REAL
#define SDL_RenderDrawLineF SDL_RenderDrawLineF_REAL
#define SDL_RenderDrawLinesF SDL_RenderDrawLinesF_REAL
#define SDL_RenderDrawRectF SDL_RenderDrawRectF_REAL
#define SDL_RenderDrawRectsF SDL_RenderDrawRectsF_REAL
#define SDL_RenderFillRectF SDL_RenderFillRectF_REAL
#define SDL_RenderFillRectsF SDL_RenderFillRectsF_REAL
#define SDL_RenderCopyF SDL_RenderCopyF_REAL
#define SDL_RenderCopyExF SDL_RenderCopyExF_REAL

View File

@ -739,3 +739,13 @@ SDL_DYNAPI_PROC(void,SDL_SensorUpdate,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return)
SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayOrientation,(int a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayOrientation,(int a),(a),return)
SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawPointF,(SDL_Renderer *a, float b, float c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawPointsF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawLineF,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawLinesF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderFillRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_RenderFillRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderCopyF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_RenderCopyExF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_RendererFlip g),(a,b,c,d,e,f,g),return)

View File

@ -2157,31 +2157,37 @@ SDL_RenderClear(SDL_Renderer * renderer)
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
} }
/* !!! FIXME: delete all the duplicate code for the integer versions in 2.1,
!!! FIXME: making the floating point versions the only available APIs. */
int int
SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y) SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
{ {
SDL_Point point; const SDL_FPoint fpoint = { (float) x, (float) y };
int retval; return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
}
point.x = x; int
point.y = y; SDL_RenderDrawPointF(SDL_Renderer * renderer, float x, float y)
retval = SDL_RenderDrawPoints(renderer, &point, 1); {
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); const SDL_FPoint fpoint = { x, y };
return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
} }
static int static int
RenderDrawPointsWithRects(SDL_Renderer * renderer, RenderDrawPointsWithRects(SDL_Renderer * renderer,
const SDL_Point * points, int count) const SDL_Point * points, const int count)
{ {
SDL_FRect *frects;
int i;
int retval = -1; int retval = -1;
SDL_bool isstack; SDL_bool isstack;
SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
int i;
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (!frects) { if (!frects) {
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
frects[i].x = points[i].x * renderer->scale.x; frects[i].x = points[i].x * renderer->scale.x;
frects[i].y = points[i].y * renderer->scale.y; frects[i].y = points[i].y * renderer->scale.y;
@ -2239,21 +2245,148 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
} }
static int
RenderDrawPointsWithRectsF(SDL_Renderer * renderer,
const SDL_FPoint * fpoints, const int count)
{
int retval = -1;
SDL_bool isstack;
SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
int i;
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
frects[i].x = fpoints[i].x * renderer->scale.x;
frects[i].y = fpoints[i].y * renderer->scale.y;
frects[i].w = renderer->scale.x;
frects[i].h = renderer->scale.y;
}
retval = QueueCmdFillRects(renderer, frects, count);
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int
SDL_RenderDrawPointsF(SDL_Renderer * renderer,
const SDL_FPoint * points, int count)
{
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!points) {
return SDL_SetError("SDL_RenderDrawFPoints(): Passed NULL points");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
return RenderDrawPointsWithRectsF(renderer, points, count);
}
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
fpoints[i].x = points[i].x * renderer->scale.x;
fpoints[i].y = points[i].y * renderer->scale.y;
}
retval = QueueCmdDrawPoints(renderer, fpoints, count);
SDL_small_free(fpoints, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int int
SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
{ {
SDL_Point points[2]; const SDL_FPoint points[2] = { { (float) x1, (float) y1 }, { (float) x2, (float) y2 } };
return SDL_RenderDrawLinesF(renderer, points, 2);
}
points[0].x = x1; int
points[0].y = y1; SDL_RenderDrawLineF(SDL_Renderer * renderer, float x1, float y1, float x2, float y2)
points[1].x = x2; {
points[1].y = y2; const SDL_FPoint points[2] = { { x1, y1 }, { x2, y2 } };
return SDL_RenderDrawLines(renderer, points, 2); return SDL_RenderDrawLinesF(renderer, points, 2);
} }
static int static int
RenderDrawLinesWithRects(SDL_Renderer * renderer, RenderDrawLinesWithRects(SDL_Renderer * renderer,
const SDL_Point * points, int count) const SDL_Point * points, const int count)
{
SDL_FRect *frect;
SDL_FRect *frects;
SDL_FPoint fpoints[2];
int i, nrects = 0;
int retval = 0;
SDL_bool isstack;
frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count-1; ++i) {
if (points[i].x == points[i+1].x) {
const int minY = SDL_min(points[i].y, points[i+1].y);
const int maxY = SDL_max(points[i].y, points[i+1].y);
frect = &frects[nrects++];
frect->x = points[i].x * renderer->scale.x;
frect->y = minY * renderer->scale.y;
frect->w = renderer->scale.x;
frect->h = (maxY - minY + 1) * renderer->scale.y;
} else if (points[i].y == points[i+1].y) {
const int minX = SDL_min(points[i].x, points[i+1].x);
const int maxX = SDL_max(points[i].x, points[i+1].x);
frect = &frects[nrects++];
frect->x = minX * renderer->scale.x;
frect->y = points[i].y * renderer->scale.y;
frect->w = (maxX - minX + 1) * renderer->scale.x;
frect->h = renderer->scale.y;
} else {
/* FIXME: We can't use a rect for this line... */
fpoints[0].x = points[i].x * renderer->scale.x;
fpoints[0].y = points[i].y * renderer->scale.y;
fpoints[1].x = points[i+1].x * renderer->scale.x;
fpoints[1].y = points[i+1].y * renderer->scale.y;
retval += QueueCmdDrawLines(renderer, fpoints, 2);
}
}
retval += QueueCmdFillRects(renderer, frects, nrects);
SDL_small_free(frects, isstack);
if (retval < 0) {
retval = -1;
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
static int
RenderDrawLinesWithRectsF(SDL_Renderer * renderer,
const SDL_FPoint * points, const int count)
{ {
SDL_FRect *frect; SDL_FRect *frect;
SDL_FRect *frects; SDL_FRect *frects;
@ -2349,20 +2482,83 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
} }
int
SDL_RenderDrawLinesF(SDL_Renderer * renderer,
const SDL_FPoint * points, int count)
{
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!points) {
return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
}
if (count < 2) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
return RenderDrawLinesWithRectsF(renderer, points, count);
}
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
fpoints[i].x = points[i].x * renderer->scale.x;
fpoints[i].y = points[i].y * renderer->scale.y;
}
retval = QueueCmdDrawLines(renderer, fpoints, count);
SDL_small_free(fpoints, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
int int
SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect) SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
{ {
SDL_Rect full_rect; SDL_FRect frect;
SDL_Point points[5]; SDL_FRect *prect = NULL;
if (rect) {
frect.x = (float) rect->x;
frect.y = (float) rect->y;
frect.w = (float) rect->w;
frect.h = (float) rect->h;
prect = &frect;
}
return SDL_RenderDrawRectF(renderer, prect);
}
int
SDL_RenderDrawRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
{
SDL_FRect frect;
SDL_FPoint points[5];
CHECK_RENDERER_MAGIC(renderer, -1); CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */ /* If 'rect' == NULL, then outline the whole surface */
if (!rect) { if (!rect) {
SDL_RenderGetViewport(renderer, &full_rect); SDL_Rect r;
full_rect.x = 0; SDL_RenderGetViewport(renderer, &r);
full_rect.y = 0; frect.x = 0.0f;
rect = &full_rect; frect.y = 0.0f;
frect.w = (float) r.w;
frect.h = (float) r.h;
rect = &frect;
} }
points[0].x = rect->x; points[0].x = rect->x;
@ -2375,7 +2571,7 @@ SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
points[3].y = rect->y+rect->h-1; points[3].y = rect->y+rect->h-1;
points[4].x = rect->x; points[4].x = rect->x;
points[4].y = rect->y; points[4].y = rect->y;
return SDL_RenderDrawLines(renderer, points, 5); return SDL_RenderDrawLinesF(renderer, points, 5);
} }
int int
@ -2406,21 +2602,76 @@ SDL_RenderDrawRects(SDL_Renderer * renderer,
return 0; return 0;
} }
int
SDL_RenderDrawRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects, int count)
{
int i;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!rects) {
return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
for (i = 0; i < count; ++i) {
if (SDL_RenderDrawRectF(renderer, &rects[i]) < 0) {
return -1;
}
}
return 0;
}
int int
SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect) SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
{ {
SDL_Rect full_rect = { 0, 0, 0, 0 }; SDL_FRect frect;
CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */
if (rect) {
frect.x = (float) rect->x;
frect.y = (float) rect->y;
frect.w = (float) rect->w;
frect.h = (float) rect->h;
} else {
SDL_Rect r;
SDL_RenderGetViewport(renderer, &r);
frect.x = 0.0f;
frect.y = 0.0f;
frect.w = (float) r.w;
frect.h = (float) r.h;
}
return SDL_RenderFillRectsF(renderer, &frect, 1);
}
int
SDL_RenderFillRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
{
SDL_FRect frect;
CHECK_RENDERER_MAGIC(renderer, -1); CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */ /* If 'rect' == NULL, then outline the whole surface */
if (!rect) { if (!rect) {
SDL_RenderGetViewport(renderer, &full_rect); SDL_Rect r;
full_rect.x = 0; SDL_RenderGetViewport(renderer, &r);
full_rect.y = 0; frect.x = 0.0f;
rect = &full_rect; frect.y = 0.0f;
frect.w = (float) r.w;
frect.h = (float) r.h;
rect = &frect;
} }
return SDL_RenderFillRects(renderer, rect, 1); return SDL_RenderFillRectsF(renderer, rect, 1);
} }
int int
@ -2464,13 +2715,124 @@ SDL_RenderFillRects(SDL_Renderer * renderer,
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
} }
int
SDL_RenderFillRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects, int count)
{
SDL_FRect *frects;
int i;
int retval;
SDL_bool isstack;
CHECK_RENDERER_MAGIC(renderer, -1);
if (!rects) {
return SDL_SetError("SDL_RenderFillFRects(): Passed NULL rects");
}
if (count < 1) {
return 0;
}
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
}
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
for (i = 0; i < count; ++i) {
frects[i].x = rects[i].x * renderer->scale.x;
frects[i].y = rects[i].y * renderer->scale.y;
frects[i].w = rects[i].w * renderer->scale.x;
frects[i].h = rects[i].h * renderer->scale.y;
}
retval = QueueCmdFillRects(renderer, frects, count);
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
{
return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
}
/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
static SDL_bool
SDL_HasIntersectionF(const SDL_FRect * A, const SDL_FRect * B)
{
float Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_FRectEmpty(A) || SDL_FRectEmpty(B)) {
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
return SDL_TRUE;
}
int int
SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect) const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{ {
SDL_Rect real_srcrect = { 0, 0, 0, 0 }; SDL_FRect dstfrect;
SDL_Rect real_dstrect = { 0, 0, 0, 0 }; SDL_FRect *pdstfrect = NULL;
SDL_FRect frect; if (dstrect) {
dstfrect.x = (float) dstrect->x;
dstfrect.y = (float) dstrect->y;
dstfrect.w = (float) dstrect->w;
dstfrect.h = (float) dstrect->h;
pdstfrect = &dstfrect;
}
return SDL_RenderCopyF(renderer, texture, srcrect, pdstfrect);
}
int
SDL_RenderCopyF(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
SDL_Rect real_srcrect;
SDL_FRect real_dstrect;
SDL_Rect r;
int retval; int retval;
CHECK_RENDERER_MAGIC(renderer, -1); CHECK_RENDERER_MAGIC(renderer, -1);
@ -2495,11 +2857,13 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
} }
} }
SDL_RenderGetViewport(renderer, &real_dstrect); SDL_RenderGetViewport(renderer, &r);
real_dstrect.x = 0; real_dstrect.x = 0.0f;
real_dstrect.y = 0; real_dstrect.y = 0.0f;
real_dstrect.w = (float) r.w;
real_dstrect.h = (float) r.h;
if (dstrect) { if (dstrect) {
if (!SDL_HasIntersection(dstrect, &real_dstrect)) { if (!SDL_HasIntersectionF(dstrect, &real_dstrect)) {
return 0; return 0;
} }
real_dstrect = *dstrect; real_dstrect = *dstrect;
@ -2509,31 +2873,56 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
texture = texture->native; texture = texture->native;
} }
frect.x = real_dstrect.x * renderer->scale.x; real_dstrect.x *= renderer->scale.x;
frect.y = real_dstrect.y * renderer->scale.y; real_dstrect.y *= renderer->scale.y;
frect.w = real_dstrect.w * renderer->scale.x; real_dstrect.w *= renderer->scale.x;
frect.h = real_dstrect.h * renderer->scale.y; real_dstrect.h *= renderer->scale.y;
texture->last_command_generation = renderer->render_command_generation; texture->last_command_generation = renderer->render_command_generation;
retval = QueueCmdCopy(renderer, texture, &real_srcrect, &frect); retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
} }
int int
SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect, const SDL_Rect * srcrect, const SDL_Rect * dstrect,
const double angle, const SDL_Point *center, const SDL_RendererFlip flip) const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
{ {
SDL_Rect real_srcrect = { 0, 0, 0, 0 }; SDL_FRect dstfrect;
SDL_Rect real_dstrect = { 0, 0, 0, 0 }; SDL_FRect *pdstfrect = NULL;
SDL_Point real_center;
SDL_FRect frect;
SDL_FPoint fcenter; SDL_FPoint fcenter;
SDL_FPoint *pfcenter = NULL;
if (dstrect) {
dstfrect.x = (float) dstrect->x;
dstfrect.y = (float) dstrect->y;
dstfrect.w = (float) dstrect->w;
dstfrect.h = (float) dstrect->h;
pdstfrect = &dstfrect;
}
if (center) {
fcenter.x = (float) center->x;
fcenter.y = (float) center->y;
pfcenter = &fcenter;
}
return SDL_RenderCopyExF(renderer, texture, srcrect, pdstfrect, angle, pfcenter, flip);
}
int
SDL_RenderCopyExF(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
SDL_Rect real_srcrect;
SDL_FRect real_dstrect;
SDL_FPoint real_center;
int retval;
if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */ if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */
return SDL_RenderCopy(renderer, texture, srcrect, dstrect); return SDL_RenderCopyF(renderer, texture, srcrect, dstrect);
} }
CHECK_RENDERER_MAGIC(renderer, -1); CHECK_RENDERER_MAGIC(renderer, -1);
@ -2565,9 +2954,12 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
if (dstrect) { if (dstrect) {
real_dstrect = *dstrect; real_dstrect = *dstrect;
} else { } else {
SDL_RenderGetViewport(renderer, &real_dstrect); SDL_Rect r;
real_dstrect.x = 0; SDL_RenderGetViewport(renderer, &r);
real_dstrect.y = 0; real_dstrect.x = 0.0f;
real_dstrect.y = 0.0f;
real_dstrect.w = (float) r.w;
real_dstrect.h = (float) r.h;
} }
if (texture->native) { if (texture->native) {
@ -2577,21 +2969,22 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
if (center) { if (center) {
real_center = *center; real_center = *center;
} else { } else {
real_center.x = real_dstrect.w/2; real_center.x = real_dstrect.w / 2.0f;
real_center.y = real_dstrect.h/2; real_center.y = real_dstrect.h / 2.0f;
} }
frect.x = real_dstrect.x * renderer->scale.x; real_dstrect.x *= renderer->scale.x;
frect.y = real_dstrect.y * renderer->scale.y; real_dstrect.y *= renderer->scale.y;
frect.w = real_dstrect.w * renderer->scale.x; real_dstrect.w *= renderer->scale.x;
frect.h = real_dstrect.h * renderer->scale.y; real_dstrect.h *= renderer->scale.y;
fcenter.x = real_center.x * renderer->scale.x; real_center.x *= renderer->scale.x;
fcenter.y = real_center.y * renderer->scale.y; real_center.y *= renderer->scale.y;
texture->last_command_generation = renderer->render_command_generation; texture->last_command_generation = renderer->render_command_generation;
return QueueCmdCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip); retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
} }
int int

View File

@ -39,20 +39,6 @@ typedef enum
SDL_ScaleModeBest SDL_ScaleModeBest
} SDL_ScaleMode; } SDL_ScaleMode;
typedef struct
{
float x;
float y;
} SDL_FPoint;
typedef struct
{
float x;
float y;
float w;
float h;
} SDL_FRect;
/* Define the SDL texture structure */ /* Define the SDL texture structure */
struct SDL_Texture struct SDL_Texture
{ {