We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 1181 - SDL_RenderCopyFlipped
Summary: SDL_RenderCopyFlipped
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: HG 2.0
Hardware: x86 Windows 7
: P2 enhancement
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-09 16:45 UTC by Mason Wheeler
Modified: 2012-06-21 07:51 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mason Wheeler 2011-04-09 16:45:53 UTC
Adding support for a RenderCopy operation flipped around the X, Y or both axes.

Add the following two definitions to SDL_render.h:

typedef enum
{
	SDL_RENDERFLIP_HORIZ = 0x00000001,
	SDL_RENDERFLIP_VERT  = 0x00000002,
	SDL_RENDERFLIP_BOTH  = 0x00000003
} SDL_RenderFlip;

...

/**
 *  \brief Copy a portion of the texture to the current rendering target, flipped
 *         around one or both axes.
 *  
 *  \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 axes      Which axes to flip the image around.
 *  
 *  \return 0 on success, or -1 on error
 */
extern DECLSPEC int SDLCALL SDL_RenderCopyFlipped(SDL_Renderer * renderer,
		  SDL_Texture * texture,
		  const SDL_Rect * srcrect,
		  const SDL_Rect * dstrect,
		  SDL_RenderFlip axes);



Then replace the implementation of SDL_RenderCopy with:

SDL_bool SDL_ClipRects(SDL_Renderer * renderer, SDL_Texture * texture,
               const SDL_Rect * srcrect, const SDL_Rect * dstrect,
			   SDL_Rect * real_srcrect, SDL_Rect * real_dstrect)
{
    real_srcrect->x = 0;
    real_srcrect->y = 0;
    real_srcrect->w = texture->w;
    real_srcrect->h = texture->h;
    if (srcrect) {
        if (!SDL_IntersectRect(srcrect, real_srcrect, real_srcrect)) {
			return SDL_FALSE;
        }
    }

    real_dstrect->x = 0;
    real_dstrect->y = 0;
    real_dstrect->w = renderer->viewport.w;
    real_dstrect->h = renderer->viewport.h;
    if (dstrect) {
        if (!SDL_IntersectRect(dstrect, real_dstrect, real_dstrect)) {
            return SDL_FALSE;
        }
        /* Clip srcrect by the same amount as dstrect was clipped */
        if (dstrect->w != real_dstrect->w) {
            int deltax = (real_dstrect->x - dstrect->x);
            int deltaw = (real_dstrect->w - dstrect->w);
            real_srcrect->x += (deltax * real_srcrect->w) / dstrect->w;
            real_srcrect->w += (deltaw * real_srcrect->w) / dstrect->w;
        }
        if (dstrect->h != real_dstrect->h) {
            int deltay = (real_dstrect->y - dstrect->y);
            int deltah = (real_dstrect->h - dstrect->h);
            real_srcrect->y += (deltay * real_srcrect->h) / dstrect->h;
            real_srcrect->h += (deltah * real_srcrect->h) / dstrect->h;
        }
    }
	return SDL_TRUE;
}

int
SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{
    SDL_Rect real_srcrect;
    SDL_Rect real_dstrect;

    CHECK_RENDERER_MAGIC(renderer, -1);
    CHECK_TEXTURE_MAGIC(texture, -1);

    if (renderer != texture->renderer) {
        SDL_SetError("Texture was not created with this renderer");
        return -1;
    }

	if (!SDL_ClipRects(renderer, texture, srcrect, dstrect, &real_srcrect,
		          &real_dstrect))
	  return 0;

    if (texture->native) {
        texture = texture->native;
    }

    return renderer->RenderCopy(renderer, texture, &real_srcrect,
                                &real_dstrect);
}

int
SDL_RenderCopyFlipped(SDL_Renderer * renderer, SDL_Texture * texture,
                      const SDL_Rect * srcrect, const SDL_Rect * dstrect,
					  int axes)
{
    SDL_Rect real_srcrect;
    SDL_Rect real_dstrect;

    CHECK_RENDERER_MAGIC(renderer, -1);
    CHECK_TEXTURE_MAGIC(texture, -1);

    if (renderer != texture->renderer) {
        SDL_SetError("Texture was not created with this renderer");
        return -1;
    }

	if (!SDL_ClipRects(renderer, texture, srcrect, dstrect, &real_srcrect,
		          &real_dstrect))
	  return 0;

    if (texture->native) {
        texture = texture->native;
    }

	if (axes & SDL_RENDERFLIP_HORIZ)
	{
		real_dstrect.x += real_dstrect.w;
		real_dstrect.w *= -1;
	}

	if (axes & SDL_RENDERFLIP_VERT)
	{
		real_dstrect.y += real_dstrect.h;
		real_dstrect.h *= -1;
	}

    return renderer->RenderCopy(renderer, texture, &real_srcrect,
                                &real_dstrect);
}
Comment 1 Sam Lantinga 2012-01-07 00:59:00 UTC
Does this work for the software and Direct3D renderers as well?
Comment 2 Mason Wheeler 2012-01-08 05:31:23 UTC
(In reply to comment #1)
> Does this work for the software and Direct3D renderers as well?

It should work for Direct3D, for the same reason it works for OpenGL: all it does is reverse the vertices for the texture coordinates.  Not sure how it will work with non-accelerated renderers that don't use the same system.
Comment 3 Sam Lantinga 2012-01-08 10:48:53 UTC
I'm pretty sure the software renderer wouldn't do the right thing. ;)

There's very similar discussion in bug 1308, maybe you want to drop by and comment?
Comment 4 Gabriel Jacobo 2012-06-21 07:51:57 UTC
SDL_RenderCopyEx has landed.