Switched over to poly-polygon region building and shape-tree traversal for Win32.
authoregottlieb
Tue, 10 Aug 2010 15:39:46 -0400
changeset 4844 c4f5bcaf7572
parent 4843 0998d1b5dd23
child 4845 61cb2d20a46f
Switched over to poly-polygon region building and shape-tree traversal for Win32.
src/video/win32/SDL_win32shape.c
--- a/src/video/win32/SDL_win32shape.c	Mon Aug 09 20:32:15 2010 -0400
+++ b/src/video/win32/SDL_win32shape.c	Tue Aug 10 15:39:46 2010 -0400
@@ -42,22 +42,40 @@
     return result;
 }
 
+typedef struct {
+	POINT corners[4];
+	void* next;
+} SDL_ShapeRect;
+
 void
-CombineRectRegions(SDL_ShapeTree* node, void* closure) {
-    HRGN* mask_region = (HRGN *)closure;
+CombineRectRegions(SDL_ShapeTree* node,void* closure) {
+    SDL_ShapeRect* rect_list = *((SDL_ShapeRect**)closure);
     if(node->kind == OpaqueShape) {
-        HRGN temp_region = CreateRectRgn(node->data.shape.x,node->data.shape.y,node->data.shape.w,node->data.shape.h);
-        CombineRgn(*mask_region,*mask_region,temp_region, RGN_OR);
-        DeleteObject(temp_region);
+        SDL_ShapeRect* rect = SDL_malloc(sizeof(SDL_ShapeRect));
+        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);
+}
+
 int
 Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) {
     SDL_ShapeData *data;
     HRGN mask_region;
-    SDL_WindowData *windowdata;
-    HWND hwnd;
+	SDL_ShapeRect* rects = NULL,*old = NULL;
+	Uint16 num_rects = 0,i = 0;
+	int* polygonVertexNumbers = NULL;
+	POINT* polygons = NULL;
 
     if (shaper == NULL || shape == NULL)
         return SDL_INVALID_SHAPE_ARGUMENT;
@@ -67,21 +85,31 @@
     data = (SDL_ShapeData*)shaper->driverdata;
     if(data->mask_tree != NULL)
         SDL_FreeShapeTree(&data->mask_tree);
-    data->mask_tree = SDL_CalculateShapeTree(*shapeMode,shape,SDL_FALSE);
+    data->mask_tree = SDL_CalculateShapeTree(*shapeMode,shape);
     
-    /*
-     * Start with empty region 
-     */
-    mask_region = CreateRectRgn(0, 0, 0, 0);
-    
-    SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region);
-    
+    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[i / 4].corners[i % 4];
+        if(i % 4 == 3) {
+            old = rects;
+            rects = rects->next;
+            SDL_free(old);
+		}
+	}
+
     /*
      * Set the new region mask for the window 
      */
-    windowdata=(SDL_WindowData *)(shaper->window->driverdata);
-    hwnd = windowdata->hwnd;
-    SetWindowRgn(hwnd, mask_region, TRUE);
+	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;
 }