From a4f336faee0b95a10dc68753410da8016dcde4d8 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <slouken@libsdl.org>
Date: Mon, 17 Apr 2006 05:38:33 +0000
Subject: [PATCH] Fixed bug #189

Clip the overlay destination rectangle to the screen area on X11

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401649
---
 src/video/x11/SDL_x11yuv.c | 47 ++++++++++++++++++++++++++++++++++----
 test/testoverlay2.c        |  4 ++++
 2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/src/video/x11/SDL_x11yuv.c b/src/video/x11/SDL_x11yuv.c
index 22bbda11..30953874 100644
--- a/src/video/x11/SDL_x11yuv.c
+++ b/src/video/x11/SDL_x11yuv.c
@@ -357,20 +357,59 @@ void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
 int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
 {
 	struct private_yuvhwdata *hwdata;
+	int srcx, srcy, srcw, srch;
+	int dstx, dsty, dstw, dsth;
 
 	hwdata = overlay->hwdata;
+
+	/* Clip the rectangle to the screen area */
+	srcx = 0;
+	srcy = 0;
+	srcw = overlay->w;
+	srch = overlay->h;
+	dstx = dstrect->x;
+	dsty = dstrect->y;
+	dstw = dstrect->w;
+	dsth = dstrect->h;
+	if ( dstx < 0 ) {
+		srcw += (dstx * overlay->w) / dstrect->w;
+		dstw += dstx;
+		srcx -= (dstx * overlay->w) / dstrect->w;
+		dstx = 0;
+	}
+	if ( (dstx+dstw) > this->screen->w ) {
+		int extra = (dstx+dstw - this->screen->w);
+		srcw -= (extra * overlay->w) / dstrect->w;
+		dstw -= extra;
+	}
+	if ( dsty < 0 ) {
+		srch += (dsty * overlay->h) / dstrect->h;
+		dsth += dsty;
+		srcy -= (dsty * overlay->h) / dstrect->h;
+		dsty = 0;
+	}
+	if ( (dsty+dsth) > this->screen->h ) {
+		int extra = (dsty+dsth - this->screen->h);
+		srch -= (extra * overlay->h) / dstrect->h;
+		dsth -= extra;
+	}
+	if ( srcw <= 0 || srch <= 0 ||
+	     srch <= 0 || dsth <= 0 ) {
+		return;
+	}
+
 #ifndef NO_SHARED_MEMORY
 	if ( hwdata->yuv_use_mitshm ) {
 		SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC,
-	              hwdata->image, 0, 0, overlay->w, overlay->h,
-	              dstrect->x, dstrect->y, dstrect->w, dstrect->h, False);
+	              hwdata->image,
+		      srcx, srcy, srcw, srch, dstx, dsty, dstw, dsth, False);
 	}
 	else
 #endif
 	{
 		SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC,
-				     hwdata->image, 0, 0, overlay->w, overlay->h,
-				     dstrect->x, dstrect->y, dstrect->w, dstrect->h);
+				     hwdata->image,
+		                     srcx, srcy, srcw, srch, dstx, dsty, dstw, dsth);
 	}
 	XSync(GFX_Display, False);
 	return(0);
diff --git a/test/testoverlay2.c b/test/testoverlay2.c
index 28cd3dd7..5f491f22 100644
--- a/test/testoverlay2.c
+++ b/test/testoverlay2.c
@@ -526,6 +526,10 @@ int main(int argc, char **argv)
                          resized=1;
                      }
                      break;
+                case SDL_MOUSEBUTTONDOWN:
+                     overlayrect.x = event.button.x - overlayrect.w/2;
+                     overlayrect.y = event.button.y - overlayrect.h/2;
+                     break;
                 case SDL_KEYDOWN:
                      if (event.key.keysym.sym == SDLK_SPACE)
                      {
-- 
2.18.1