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.
--- a/src/video/SDL_shape.c Sat Aug 14 16:14:36 2010 -0400
+++ b/src/video/SDL_shape.c Sat Aug 14 20:29:51 2010 -0400
@@ -156,7 +156,7 @@
break;
case(ShapeModeColorKey):
key = mode.parameters.colorKey;
- pixel_opaque = ((key.r == r && key.g == g && key.b == b) ? SDL_TRUE : SDL_FALSE);
+ pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
break;
}
if(last_opaque == -1)
@@ -170,14 +170,14 @@
next.x = dimensions.x;
next.y = dimensions.y;
result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
- next.x = dimensions.w / 2;
+ next.x += next.w;
//Unneeded: next.y = dimensions.y;
result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.x;
- next.y = dimensions.h / 2;
+ next.y += next.h;
result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
- next.x = dimensions.w / 2;
- //Unneeded: next.y = dimensions.h / 2 + 1;
+ next.x += next.w;
+ //Unneeded: next.y = dimensions.y + dimensions.h /2;
result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
return result;
}
@@ -214,15 +214,15 @@
}
void
-SDL_FreeShapeTree(SDL_ShapeTree** shapeTree) {
- if((*shapeTree)->kind == QuadShape) {
- SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.upleft);
- SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.upright);
- SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.downleft);
- SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.downright);
+SDL_FreeShapeTree(SDL_ShapeTree** shape_tree) {
+ if((*shape_tree)->kind == QuadShape) {
+ SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upleft);
+ SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upright);
+ SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downleft);
+ SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downright);
}
- SDL_free(*shapeTree);
- *shapeTree = NULL;
+ SDL_free(*shape_tree);
+ *shape_tree = NULL;
}
int
@@ -240,7 +240,6 @@
result = window->display->device->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
window->shaper->hasshape = SDL_TRUE;
if((window->shaper->usershownflag & SDL_WINDOW_SHOWN) == SDL_WINDOW_SHOWN) {
- SDL_SetWindowPosition(window,window->x,window->y);
SDL_ShowWindow(window);
window->shaper->usershownflag &= !SDL_WINDOW_SHOWN;
}
--- a/src/video/SDL_shape_internals.h Sat Aug 14 16:14:36 2010 -0400
+++ b/src/video/SDL_shape_internals.h Sat Aug 14 20:29:51 2010 -0400
@@ -57,7 +57,7 @@
extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb);
extern SDL_ShapeTree* SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape);
extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* closure);
-extern void SDL_FreeShapeTree(SDL_ShapeTree** shapeTree);
+extern void SDL_FreeShapeTree(SDL_ShapeTree** shape_tree);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
--- 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;
}