Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Mostly seem to have fixed SDL_CalculateShapeTree. Mostly. There still…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
egottlieb committed Aug 15, 2010
1 parent 08f69d4 commit f2f3bcb
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 68 deletions.
27 changes: 13 additions & 14 deletions src/video/SDL_shape.c
Expand Up @@ -156,7 +156,7 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec
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)
Expand All @@ -170,14 +170,14 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec
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;
}
Expand Down Expand Up @@ -214,15 +214,15 @@ SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* c
}

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
Expand All @@ -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);
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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/video/SDL_shape_internals.h
Expand Up @@ -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 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
Expand Down
68 changes: 15 additions & 53 deletions src/video/win32/SDL_win32shape.c
Expand Up @@ -21,6 +21,7 @@
*/

#include <stdio.h>
#include "SDL_assert.h"
#include "SDL_win32shape.h"
#include "SDL_win32video.h"

Expand All @@ -43,47 +44,31 @@ Win32_CreateShaper(SDL_Window * window) {
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;
Expand All @@ -95,33 +80,10 @@ Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShape
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;
}
Expand Down

0 comments on commit f2f3bcb

Please sign in to comment.