diff src/video/win32/SDL_win32shape.c @ 4850:14870d46ee2d

Mostly seem to have fixed SDL_CalculateShapeTree. Mostly. There still seem to be some rendering artifacts, stepping effects, and such on Windows -- which indicates subtle logic errors in SDL_CalculateShapeTree(). Oh well, back into the salt mine.
author egottlieb
date Sat, 14 Aug 2010 20:29:51 -0400
parents 0b918c186938
children 5624fb0190b5
line wrap: on
line diff
--- a/src/video/win32/SDL_win32shape.c	Sat Aug 14 16:14:36 2010 -0400
+++ b/src/video/win32/SDL_win32shape.c	Sat Aug 14 20:29:51 2010 -0400
@@ -21,6 +21,7 @@
 */
 
 #include <stdio.h>
+#include "SDL_assert.h"
 #include "SDL_win32shape.h"
 #include "SDL_win32video.h"
 
@@ -43,47 +44,31 @@
     return result;
 }
 
-typedef struct {
-	POINT corners[4];
-	void* next;
-} SDL_ShapeRect;
-
 void
 CombineRectRegions(SDL_ShapeTree* node,void* closure) {
 	char debug_str[200];
-    SDL_ShapeRect* rect_list = *((SDL_ShapeRect**)closure);
+    HRGN mask_region = *((HRGN*)closure),temp_region = NULL;
     if(node->kind == OpaqueShape) {
-        SDL_ShapeRect* rect = SDL_malloc(sizeof(SDL_ShapeRect));
-		sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
+        //Win32 API regions exclude their outline, so we widen the region by one pixel in each direction to include the real outline.
+        sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
                   node->data.shape.x,node->data.shape.y,
 				  node->data.shape.x + node->data.shape.w,node->data.shape.y + node->data.shape.h);
         OutputDebugStringA(debug_str);
 		OutputDebugStringA("Converting SDL_ShapeTree opaque node to Windows rectangle.\n");
-        rect->corners[0].x = node->data.shape.x; rect->corners[0].y = node->data.shape.y;
-        rect->corners[1].x = node->data.shape.x + node->data.shape.w; rect->corners[1].y = node->data.shape.y;
-        rect->corners[2].x = node->data.shape.x + node->data.shape.w; rect->corners[2].y = node->data.shape.y + node->data.shape.h;
-        rect->corners[3].x = node->data.shape.x; rect->corners[3].y = node->data.shape.y + node->data.shape.h;
-        rect->next = *((SDL_ShapeRect**)closure);
-        *((SDL_ShapeRect**)closure) = rect;
-    }
-}
-
-Uint32 num_shape_rects(SDL_ShapeRect* rect) {
-    if(rect == NULL)
-        return 0;
-	else
-		return 1 + num_shape_rects(rect->next);
+        temp_region = CreateRectRgn(node->data.shape.x - 1,node->data.shape.y - 1,node->data.shape.x + node->data.shape.w + 1,node->data.shape.y + node->data.shape.h + 1);
+        if(mask_region != NULL) {
+            CombineRgn(mask_region,mask_region,temp_region,RGN_OR);
+            DeleteObject(temp_region);
+		}
+		else
+            *((HRGN*)closure) = temp_region;
+	}
 }
 
 int
 Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
     SDL_ShapeData *data;
-    HRGN mask_region;
-	SDL_ShapeRect* rects = NULL,*old = NULL;
-	Uint16 num_rects = 0,i = 0;
-	int* polygonVertexNumbers = NULL;
-	POINT* polygons = NULL;
-	char debug_str[200];
+    HRGN mask_region = NULL;
 
     if (shaper == NULL || shape == NULL)
         return SDL_INVALID_SHAPE_ARGUMENT;
@@ -95,33 +80,10 @@
         SDL_FreeShapeTree(&data->mask_tree);
     data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape);
     
-    SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&rects);
-    num_rects = num_shape_rects(rects);
-    polygonVertexNumbers = (int*)SDL_malloc(sizeof(int)*num_rects);
-    for(i=0;i<num_rects;i++)
-        polygonVertexNumbers[i] = 4;
-    polygons = (POINT*)SDL_malloc(sizeof(POINT)*4*num_rects);
-    for(i=0;i<num_rects*4;i++) {
-		polygons[i] = rects->corners[i % 4];
-        if(i % 4 == 3) {
-			sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
-                      rects->corners[0].x,rects->corners[0].y,
-                      rects->corners[2].x,rects->corners[2].y);
-            OutputDebugStringA(debug_str);
-            old = rects;
-            rects = rects->next;
-            SDL_free(old);
-		}
-	}
+    SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region);
+	SDL_assert(mask_region != NULL);
 
-    /*
-     * Set the new region mask for the window 
-     */
-    mask_region = CreatePolyPolygonRgn(polygons,polygonVertexNumbers,num_rects,WINDING);
     SetWindowRgn(((SDL_WindowData *)(shaper->window->driverdata))->hwnd, mask_region, TRUE);
-
-    SDL_free(polygons);
-    SDL_free(polygonVertexNumbers);
     
     return 0;
 }