comparison src/video/win32/SDL_win32shape.c @ 4850:14870d46ee2d

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.
author egottlieb
date Sat, 14 Aug 2010 20:29:51 -0400
parents 0b918c186938
children 5624fb0190b5
comparison
equal deleted inserted replaced
4849:0b918c186938 4850:14870d46ee2d
19 Eli Gottlieb 19 Eli Gottlieb
20 eligottlieb@gmail.com 20 eligottlieb@gmail.com
21 */ 21 */
22 22
23 #include <stdio.h> 23 #include <stdio.h>
24 #include "SDL_assert.h"
24 #include "SDL_win32shape.h" 25 #include "SDL_win32shape.h"
25 #include "SDL_win32video.h" 26 #include "SDL_win32video.h"
26 27
27 SDL_WindowShaper* 28 SDL_WindowShaper*
28 Win32_CreateShaper(SDL_Window * window) { 29 Win32_CreateShaper(SDL_Window * window) {
41 return NULL; 42 return NULL;
42 43
43 return result; 44 return result;
44 } 45 }
45 46
46 typedef struct {
47 POINT corners[4];
48 void* next;
49 } SDL_ShapeRect;
50
51 void 47 void
52 CombineRectRegions(SDL_ShapeTree* node,void* closure) { 48 CombineRectRegions(SDL_ShapeTree* node,void* closure) {
53 char debug_str[200]; 49 char debug_str[200];
54 SDL_ShapeRect* rect_list = *((SDL_ShapeRect**)closure); 50 HRGN mask_region = *((HRGN*)closure),temp_region = NULL;
55 if(node->kind == OpaqueShape) { 51 if(node->kind == OpaqueShape) {
56 SDL_ShapeRect* rect = SDL_malloc(sizeof(SDL_ShapeRect)); 52 //Win32 API regions exclude their outline, so we widen the region by one pixel in each direction to include the real outline.
57 sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n", 53 sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
58 node->data.shape.x,node->data.shape.y, 54 node->data.shape.x,node->data.shape.y,
59 node->data.shape.x + node->data.shape.w,node->data.shape.y + node->data.shape.h); 55 node->data.shape.x + node->data.shape.w,node->data.shape.y + node->data.shape.h);
60 OutputDebugStringA(debug_str); 56 OutputDebugStringA(debug_str);
61 OutputDebugStringA("Converting SDL_ShapeTree opaque node to Windows rectangle.\n"); 57 OutputDebugStringA("Converting SDL_ShapeTree opaque node to Windows rectangle.\n");
62 rect->corners[0].x = node->data.shape.x; rect->corners[0].y = node->data.shape.y; 58 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);
63 rect->corners[1].x = node->data.shape.x + node->data.shape.w; rect->corners[1].y = node->data.shape.y; 59 if(mask_region != NULL) {
64 rect->corners[2].x = node->data.shape.x + node->data.shape.w; rect->corners[2].y = node->data.shape.y + node->data.shape.h; 60 CombineRgn(mask_region,mask_region,temp_region,RGN_OR);
65 rect->corners[3].x = node->data.shape.x; rect->corners[3].y = node->data.shape.y + node->data.shape.h; 61 DeleteObject(temp_region);
66 rect->next = *((SDL_ShapeRect**)closure); 62 }
67 *((SDL_ShapeRect**)closure) = rect; 63 else
68 } 64 *((HRGN*)closure) = temp_region;
69 } 65 }
70
71 Uint32 num_shape_rects(SDL_ShapeRect* rect) {
72 if(rect == NULL)
73 return 0;
74 else
75 return 1 + num_shape_rects(rect->next);
76 } 66 }
77 67
78 int 68 int
79 Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) { 69 Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
80 SDL_ShapeData *data; 70 SDL_ShapeData *data;
81 HRGN mask_region; 71 HRGN mask_region = NULL;
82 SDL_ShapeRect* rects = NULL,*old = NULL;
83 Uint16 num_rects = 0,i = 0;
84 int* polygonVertexNumbers = NULL;
85 POINT* polygons = NULL;
86 char debug_str[200];
87 72
88 if (shaper == NULL || shape == NULL) 73 if (shaper == NULL || shape == NULL)
89 return SDL_INVALID_SHAPE_ARGUMENT; 74 return SDL_INVALID_SHAPE_ARGUMENT;
90 if(shape->format->Amask == 0 && shape_mode->mode != ShapeModeColorKey || shape->w != shaper->window->w || shape->h != shaper->window->h) 75 if(shape->format->Amask == 0 && shape_mode->mode != ShapeModeColorKey || shape->w != shaper->window->w || shape->h != shaper->window->h)
91 return SDL_INVALID_SHAPE_ARGUMENT; 76 return SDL_INVALID_SHAPE_ARGUMENT;
93 data = (SDL_ShapeData*)shaper->driverdata; 78 data = (SDL_ShapeData*)shaper->driverdata;
94 if(data->mask_tree != NULL) 79 if(data->mask_tree != NULL)
95 SDL_FreeShapeTree(&data->mask_tree); 80 SDL_FreeShapeTree(&data->mask_tree);
96 data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape); 81 data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape);
97 82
98 SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&rects); 83 SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region);
99 num_rects = num_shape_rects(rects); 84 SDL_assert(mask_region != NULL);
100 polygonVertexNumbers = (int*)SDL_malloc(sizeof(int)*num_rects);
101 for(i=0;i<num_rects;i++)
102 polygonVertexNumbers[i] = 4;
103 polygons = (POINT*)SDL_malloc(sizeof(POINT)*4*num_rects);
104 for(i=0;i<num_rects*4;i++) {
105 polygons[i] = rects->corners[i % 4];
106 if(i % 4 == 3) {
107 sprintf_s(&debug_str[0],200,"x: %u y: %u, x+w: %u, y+h: %u\n",
108 rects->corners[0].x,rects->corners[0].y,
109 rects->corners[2].x,rects->corners[2].y);
110 OutputDebugStringA(debug_str);
111 old = rects;
112 rects = rects->next;
113 SDL_free(old);
114 }
115 }
116 85
117 /*
118 * Set the new region mask for the window
119 */
120 mask_region = CreatePolyPolygonRgn(polygons,polygonVertexNumbers,num_rects,WINDING);
121 SetWindowRgn(((SDL_WindowData *)(shaper->window->driverdata))->hwnd, mask_region, TRUE); 86 SetWindowRgn(((SDL_WindowData *)(shaper->window->driverdata))->hwnd, mask_region, TRUE);
122
123 SDL_free(polygons);
124 SDL_free(polygonVertexNumbers);
125 87
126 return 0; 88 return 0;
127 } 89 }
128 90
129 int 91 int