Commit 6d464375 authored by egottlieb's avatar egottlieb

Mostly seem to have fixed SDL_CalculateShapeTree. Mostly. There still seem...

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.
parent 4e4cb86f
...@@ -156,7 +156,7 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec ...@@ -156,7 +156,7 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec
break; break;
case(ShapeModeColorKey): case(ShapeModeColorKey):
key = mode.parameters.colorKey; 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; break;
} }
if(last_opaque == -1) if(last_opaque == -1)
...@@ -170,14 +170,14 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec ...@@ -170,14 +170,14 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec
next.x = dimensions.x; next.x = dimensions.x;
next.y = dimensions.y; next.y = dimensions.y;
result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next); 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; //Unneeded: next.y = dimensions.y;
result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next); result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.x; next.x = dimensions.x;
next.y = dimensions.h / 2; next.y += next.h;
result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next); result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.w / 2; next.x += next.w;
//Unneeded: next.y = dimensions.h / 2 + 1; //Unneeded: next.y = dimensions.y + dimensions.h /2;
result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next); result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
return result; return result;
} }
...@@ -214,15 +214,15 @@ SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* c ...@@ -214,15 +214,15 @@ SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* c
} }
void void
SDL_FreeShapeTree(SDL_ShapeTree** shapeTree) { SDL_FreeShapeTree(SDL_ShapeTree** shape_tree) {
if((*shapeTree)->kind == QuadShape) { if((*shape_tree)->kind == QuadShape) {
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.upleft); SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upleft);
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.upright); SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upright);
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.downleft); SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downleft);
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.downright); SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downright);
} }
SDL_free(*shapeTree); SDL_free(*shape_tree);
*shapeTree = NULL; *shape_tree = NULL;
} }
int int
...@@ -240,7 +240,6 @@ SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *sh ...@@ -240,7 +240,6 @@ SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *sh
result = window->display->device->shape_driver.SetWindowShape(window->shaper,shape,shape_mode); result = window->display->device->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
window->shaper->hasshape = SDL_TRUE; window->shaper->hasshape = SDL_TRUE;
if((window->shaper->usershownflag & SDL_WINDOW_SHOWN) == SDL_WINDOW_SHOWN) { if((window->shaper->usershownflag & SDL_WINDOW_SHOWN) == SDL_WINDOW_SHOWN) {
SDL_SetWindowPosition(window,window->x,window->y);
SDL_ShowWindow(window); SDL_ShowWindow(window);
window->shaper->usershownflag &= !SDL_WINDOW_SHOWN; window->shaper->usershownflag &= !SDL_WINDOW_SHOWN;
} }
......
...@@ -57,7 +57,7 @@ typedef void(*SDL_TraversalFunction)(SDL_ShapeTree*,void*); ...@@ -57,7 +57,7 @@ typedef void(*SDL_TraversalFunction)(SDL_ShapeTree*,void*);
extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb); 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 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_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++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "SDL_assert.h"
#include "SDL_win32shape.h" #include "SDL_win32shape.h"
#include "SDL_win32video.h" #include "SDL_win32video.h"
...@@ -43,47 +44,31 @@ Win32_CreateShaper(SDL_Window * window) { ...@@ -43,47 +44,31 @@ Win32_CreateShaper(SDL_Window * window) {
return result; return result;
} }
typedef struct {
POINT corners[4];
void* next;
} SDL_ShapeRect;
void void
CombineRectRegions(SDL_ShapeTree* node,void* closure) { CombineRectRegions(SDL_ShapeTree* node,void* closure) {
char debug_str[200]; char debug_str[200];
SDL_ShapeRect* rect_list = *((SDL_ShapeRect**)closure); HRGN mask_region = *((HRGN*)closure),temp_region = NULL;
if(node->kind == OpaqueShape) { if(node->kind == OpaqueShape) {
SDL_ShapeRect* rect = SDL_malloc(sizeof(SDL_ShapeRect)); //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", 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.y,
node->data.shape.x + node->data.shape.w,node->data.shape.y + node->data.shape.h); node->data.shape.x + node->data.shape.w,node->data.shape.y + node->data.shape.h);
OutputDebugStringA(debug_str); OutputDebugStringA(debug_str);
OutputDebugStringA("Converting SDL_ShapeTree opaque node to Windows rectangle.\n"); 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; 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);
rect->corners[1].x = node->data.shape.x + node->data.shape.w; rect->corners[1].y = node->data.shape.y; if(mask_region != NULL) {
rect->corners[2].x = node->data.shape.x + node->data.shape.w; rect->corners[2].y = node->data.shape.y + node->data.shape.h; CombineRgn(mask_region,mask_region,temp_region,RGN_OR);
rect->corners[3].x = node->data.shape.x; rect->corners[3].y = node->data.shape.y + node->data.shape.h; DeleteObject(temp_region);
rect->next = *((SDL_ShapeRect**)closure); }
*((SDL_ShapeRect**)closure) = rect; else
} *((HRGN*)closure) = temp_region;
} }
Uint32 num_shape_rects(SDL_ShapeRect* rect) {
if(rect == NULL)
return 0;
else
return 1 + num_shape_rects(rect->next);
} }
int int
Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) { Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
SDL_ShapeData *data; SDL_ShapeData *data;
HRGN mask_region; HRGN mask_region = NULL;
SDL_ShapeRect* rects = NULL,*old = NULL;
Uint16 num_rects = 0,i = 0;
int* polygonVertexNumbers = NULL;
POINT* polygons = NULL;
char debug_str[200];
if (shaper == NULL || shape == NULL) if (shaper == NULL || shape == NULL)
return SDL_INVALID_SHAPE_ARGUMENT; return SDL_INVALID_SHAPE_ARGUMENT;
...@@ -95,33 +80,10 @@ Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShape ...@@ -95,33 +80,10 @@ Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShape
SDL_FreeShapeTree(&data->mask_tree); SDL_FreeShapeTree(&data->mask_tree);
data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape); data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape);
SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&rects); SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region);
num_rects = num_shape_rects(rects); SDL_assert(mask_region != NULL);
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);
}
}
/*
* 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); SetWindowRgn(((SDL_WindowData *)(shaper->window->driverdata))->hwnd, mask_region, TRUE);
SDL_free(polygons);
SDL_free(polygonVertexNumbers);
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment