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().
authoregottlieb
Sat, 14 Aug 2010 20:29:51 -0400
changeset 485014870d46ee2d
parent 4849 0b918c186938
child 4851 5624fb0190b5
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.
src/video/SDL_shape.c
src/video/SDL_shape_internals.h
src/video/win32/SDL_win32shape.c
     1.1 --- a/src/video/SDL_shape.c	Sat Aug 14 16:14:36 2010 -0400
     1.2 +++ b/src/video/SDL_shape.c	Sat Aug 14 20:29:51 2010 -0400
     1.3 @@ -156,7 +156,7 @@
     1.4                      break;
     1.5                  case(ShapeModeColorKey):
     1.6                      key = mode.parameters.colorKey;
     1.7 -                    pixel_opaque = ((key.r == r && key.g == g && key.b == b) ? SDL_TRUE : SDL_FALSE);
     1.8 +                    pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
     1.9                      break;
    1.10              }
    1.11              if(last_opaque == -1)
    1.12 @@ -170,14 +170,14 @@
    1.13                  next.x = dimensions.x;
    1.14                  next.y = dimensions.y;
    1.15                  result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
    1.16 -                next.x = dimensions.w / 2;
    1.17 +                next.x += next.w;
    1.18                  //Unneeded: next.y = dimensions.y;
    1.19                  result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
    1.20                  next.x = dimensions.x;
    1.21 -                next.y = dimensions.h / 2;
    1.22 +                next.y += next.h;
    1.23                  result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
    1.24 -                next.x = dimensions.w / 2;
    1.25 -                //Unneeded: next.y = dimensions.h / 2 + 1;
    1.26 +                next.x += next.w;
    1.27 +                //Unneeded: next.y = dimensions.y + dimensions.h /2;
    1.28                  result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
    1.29                  return result;
    1.30              }
    1.31 @@ -214,15 +214,15 @@
    1.32  }
    1.33  
    1.34  void
    1.35 -SDL_FreeShapeTree(SDL_ShapeTree** shapeTree) {
    1.36 -    if((*shapeTree)->kind == QuadShape) {
    1.37 -        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.upleft);
    1.38 -        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.upright);
    1.39 -        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.downleft);
    1.40 -        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shapeTree)->data.children.downright);
    1.41 +SDL_FreeShapeTree(SDL_ShapeTree** shape_tree) {
    1.42 +    if((*shape_tree)->kind == QuadShape) {
    1.43 +        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upleft);
    1.44 +        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upright);
    1.45 +        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downleft);
    1.46 +        SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downright);
    1.47      }
    1.48 -    SDL_free(*shapeTree);
    1.49 -    *shapeTree = NULL;
    1.50 +    SDL_free(*shape_tree);
    1.51 +    *shape_tree = NULL;
    1.52  }
    1.53  
    1.54  int
    1.55 @@ -240,7 +240,6 @@
    1.56      result = window->display->device->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
    1.57      window->shaper->hasshape = SDL_TRUE;
    1.58      if((window->shaper->usershownflag & SDL_WINDOW_SHOWN) == SDL_WINDOW_SHOWN) {
    1.59 -        SDL_SetWindowPosition(window,window->x,window->y);
    1.60          SDL_ShowWindow(window);
    1.61          window->shaper->usershownflag &= !SDL_WINDOW_SHOWN;
    1.62      }
     2.1 --- a/src/video/SDL_shape_internals.h	Sat Aug 14 16:14:36 2010 -0400
     2.2 +++ b/src/video/SDL_shape_internals.h	Sat Aug 14 20:29:51 2010 -0400
     2.3 @@ -57,7 +57,7 @@
     2.4  extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb);
     2.5  extern SDL_ShapeTree* SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape);
     2.6  extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* closure);
     2.7 -extern void SDL_FreeShapeTree(SDL_ShapeTree** shapeTree);
     2.8 +extern void SDL_FreeShapeTree(SDL_ShapeTree** shape_tree);
     2.9  
    2.10  /* Ends C function definitions when using C++ */
    2.11  #ifdef __cplusplus
     3.1 --- a/src/video/win32/SDL_win32shape.c	Sat Aug 14 16:14:36 2010 -0400
     3.2 +++ b/src/video/win32/SDL_win32shape.c	Sat Aug 14 20:29:51 2010 -0400
     3.3 @@ -21,6 +21,7 @@
     3.4  */
     3.5  
     3.6  #include <stdio.h>
     3.7 +#include "SDL_assert.h"
     3.8  #include "SDL_win32shape.h"
     3.9  #include "SDL_win32video.h"
    3.10  
    3.11 @@ -43,47 +44,31 @@
    3.12      return result;
    3.13  }
    3.14  
    3.15 -typedef struct {
    3.16 -	POINT corners[4];
    3.17 -	void* next;
    3.18 -} SDL_ShapeRect;
    3.19 -
    3.20  void
    3.21  CombineRectRegions(SDL_ShapeTree* node,void* closure) {
    3.22  	char debug_str[200];
    3.23 -    SDL_ShapeRect* rect_list = *((SDL_ShapeRect**)closure);
    3.24 +    HRGN mask_region = *((HRGN*)closure),temp_region = NULL;
    3.25      if(node->kind == OpaqueShape) {
    3.26 -        SDL_ShapeRect* rect = SDL_malloc(sizeof(SDL_ShapeRect));
    3.27 -		sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
    3.28 +        //Win32 API regions exclude their outline, so we widen the region by one pixel in each direction to include the real outline.
    3.29 +        sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
    3.30                    node->data.shape.x,node->data.shape.y,
    3.31  				  node->data.shape.x + node->data.shape.w,node->data.shape.y + node->data.shape.h);
    3.32          OutputDebugStringA(debug_str);
    3.33  		OutputDebugStringA("Converting SDL_ShapeTree opaque node to Windows rectangle.\n");
    3.34 -        rect->corners[0].x = node->data.shape.x; rect->corners[0].y = node->data.shape.y;
    3.35 -        rect->corners[1].x = node->data.shape.x + node->data.shape.w; rect->corners[1].y = node->data.shape.y;
    3.36 -        rect->corners[2].x = node->data.shape.x + node->data.shape.w; rect->corners[2].y = node->data.shape.y + node->data.shape.h;
    3.37 -        rect->corners[3].x = node->data.shape.x; rect->corners[3].y = node->data.shape.y + node->data.shape.h;
    3.38 -        rect->next = *((SDL_ShapeRect**)closure);
    3.39 -        *((SDL_ShapeRect**)closure) = rect;
    3.40 -    }
    3.41 -}
    3.42 -
    3.43 -Uint32 num_shape_rects(SDL_ShapeRect* rect) {
    3.44 -    if(rect == NULL)
    3.45 -        return 0;
    3.46 -	else
    3.47 -		return 1 + num_shape_rects(rect->next);
    3.48 +        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);
    3.49 +        if(mask_region != NULL) {
    3.50 +            CombineRgn(mask_region,mask_region,temp_region,RGN_OR);
    3.51 +            DeleteObject(temp_region);
    3.52 +		}
    3.53 +		else
    3.54 +            *((HRGN*)closure) = temp_region;
    3.55 +	}
    3.56  }
    3.57  
    3.58  int
    3.59  Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
    3.60      SDL_ShapeData *data;
    3.61 -    HRGN mask_region;
    3.62 -	SDL_ShapeRect* rects = NULL,*old = NULL;
    3.63 -	Uint16 num_rects = 0,i = 0;
    3.64 -	int* polygonVertexNumbers = NULL;
    3.65 -	POINT* polygons = NULL;
    3.66 -	char debug_str[200];
    3.67 +    HRGN mask_region = NULL;
    3.68  
    3.69      if (shaper == NULL || shape == NULL)
    3.70          return SDL_INVALID_SHAPE_ARGUMENT;
    3.71 @@ -95,33 +80,10 @@
    3.72          SDL_FreeShapeTree(&data->mask_tree);
    3.73      data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape);
    3.74      
    3.75 -    SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&rects);
    3.76 -    num_rects = num_shape_rects(rects);
    3.77 -    polygonVertexNumbers = (int*)SDL_malloc(sizeof(int)*num_rects);
    3.78 -    for(i=0;i<num_rects;i++)
    3.79 -        polygonVertexNumbers[i] = 4;
    3.80 -    polygons = (POINT*)SDL_malloc(sizeof(POINT)*4*num_rects);
    3.81 -    for(i=0;i<num_rects*4;i++) {
    3.82 -		polygons[i] = rects->corners[i % 4];
    3.83 -        if(i % 4 == 3) {
    3.84 -			sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
    3.85 -                      rects->corners[0].x,rects->corners[0].y,
    3.86 -                      rects->corners[2].x,rects->corners[2].y);
    3.87 -            OutputDebugStringA(debug_str);
    3.88 -            old = rects;
    3.89 -            rects = rects->next;
    3.90 -            SDL_free(old);
    3.91 -		}
    3.92 -	}
    3.93 +    SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region);
    3.94 +	SDL_assert(mask_region != NULL);
    3.95  
    3.96 -    /*
    3.97 -     * Set the new region mask for the window 
    3.98 -     */
    3.99 -    mask_region = CreatePolyPolygonRgn(polygons,polygonVertexNumbers,num_rects,WINDING);
   3.100      SetWindowRgn(((SDL_WindowData *)(shaper->window->driverdata))->hwnd, mask_region, TRUE);
   3.101 -
   3.102 -    SDL_free(polygons);
   3.103 -    SDL_free(polygonVertexNumbers);
   3.104      
   3.105      return 0;
   3.106  }