comparison src/video/SDL_shape.c @ 4813:5b4c7d7d8953

Wrote out the system for breaking shape-masks into quad-trees of rectangles, and added code to conglomerate those quad-trees of rectangles into regions for setting shapes under Win32.
author Eli Gottlieb <eligottlieb@gmail.com>
date Wed, 28 Jul 2010 23:35:24 -0400
parents 7a602fd2121f
children 93402b9dd20c
comparison
equal deleted inserted replaced
4812:06a03d08cefb 4813:5b4c7d7d8953
25 #include "SDL_video.h" 25 #include "SDL_video.h"
26 #include "SDL_sysvideo.h" 26 #include "SDL_sysvideo.h"
27 #include "SDL_pixels.h" 27 #include "SDL_pixels.h"
28 #include "SDL_surface.h" 28 #include "SDL_surface.h"
29 #include "SDL_shape.h" 29 #include "SDL_shape.h"
30 #include "SDL_shape_internals.h"
30 31
31 SDL_Window* SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) { 32 SDL_Window* SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) {
32 SDL_Window *result = SDL_CreateWindow(title,x,y,w,h,SDL_WINDOW_BORDERLESS | flags & !SDL_WINDOW_FULLSCREEN & !SDL_WINDOW_SHOWN); 33 SDL_Window *result = SDL_CreateWindow(title,x,y,w,h,SDL_WINDOW_BORDERLESS | flags & !SDL_WINDOW_FULLSCREEN & !SDL_WINDOW_SHOWN);
33 if(result != NULL) { 34 if(result != NULL) {
34 result->shaper = result->display->device->shape_driver.CreateShaper(result); 35 result->shaper = result->display->device->shape_driver.CreateShaper(result);
53 return SDL_FALSE; 54 return SDL_FALSE;
54 else 55 else
55 return (SDL_bool)(window->shaper != NULL); 56 return (SDL_bool)(window->shaper != NULL);
56 } 57 }
57 58
58 /* REQUIRES that bitmap point to a w-by-h bitmap with 1bpp. */ 59 /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
59 void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb,Uint8 value) { 60 void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb,Uint8 value) {
60 int x = 0; 61 int x = 0;
61 int y = 0; 62 int y = 0;
62 Uint8 r = 0,g = 0,b = 0,alpha = 0; 63 Uint8 r = 0,g = 0,b = 0,alpha = 0;
63 Uint8* pixel = NULL; 64 Uint8* pixel = NULL;
101 } 102 }
102 } 103 }
103 } 104 }
104 if(SDL_MUSTLOCK(shape)) 105 if(SDL_MUSTLOCK(shape))
105 SDL_UnlockSurface(shape); 106 SDL_UnlockSurface(shape);
107 }
108
109 SDL_ShapeTree* RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_bool invert,SDL_Rect dimensions) {
110 int x = 0,y = 0;
111 Uint8* pixel = NULL;
112 Uint32 pixel_value = 0;
113 Uint8 r = 0,g = 0,b = 0,a = 0;
114 SDL_bool pixel_transparent = SDL_FALSE;
115 int last_transparent = -1;
116 SDL_Color key;
117 SDL_ShapeTree* result = malloc(sizeof(SDL_ShapeTree));
118 SDL_Rect next = {0,0,0,0};
119 for(y=dimensions.y;y<dimensions.h;y++)
120 for(x=dimensions.x;x<dimensions.w;x++) {
121 pixel_value = 0;
122 pixel = (Uint8 *)(mask->pixels) + (y*mask->pitch) + (x*mask->format->BytesPerPixel);
123 switch(mask->format->BytesPerPixel) {
124 case(1):
125 pixel_value = *(Uint8*)pixel;
126 break;
127 case(2):
128 pixel_value = *(Uint16*)pixel;
129 break;
130 case(4):
131 pixel_value = *(Uint32*)pixel;
132 break;
133 }
134 SDL_GetRGBA(pixel_value,mask->format,&r,&g,&b,&a);
135 switch(mode.mode) {
136 case(ShapeModeDefault):
137 pixel_transparent = (a >= 1 ? !invert : invert);
138 break;
139 case(ShapeModeBinarizeAlpha):
140 pixel_transparent = (a >= mode.parameters.binarizationCutoff ? !invert : invert);
141 break;
142 case(ShapeModeReverseBinarizeAlpha):
143 pixel_transparent = (a <= mode.parameters.binarizationCutoff ? !invert : invert);
144 break;
145 case(ShapeModeColorKey):
146 key = mode.parameters.colorKey;
147 pixel_transparent = ((key.r == r && key.g == g && key.b == b) ? !invert : invert);
148 break;
149 }
150 if(last_transparent == -1) {
151 last_transparent = pixel_transparent;
152 break;
153 }
154 if(last_transparent != pixel_transparent) {
155 result->kind = QuadShape;
156 //These will stay the same.
157 next.w = dimensions.w / 2;
158 next.h = dimensions.h / 2;
159 //These will change from recursion to recursion.
160 next.x = dimensions.x;
161 next.y = dimensions.y;
162 result->data.children.upleft = RecursivelyCalculateShapeTree(mode,mask,invert,next);
163 next.x = dimensions.w / 2 + 1;
164 //Unneeded: next.y = dimensions.y;
165 result->data.children.upright = RecursivelyCalculateShapeTree(mode,mask,invert,next);
166 next.x = dimensions.x;
167 next.y = dimensions.h / 2 + 1;
168 result->data.children.downleft = RecursivelyCalculateShapeTree(mode,mask,invert,next);
169 next.x = dimensions.w / 2 + 1;
170 //Unneeded: next.y = dimensions.h / 2 + 1;
171 result->data.children.downright = RecursivelyCalculateShapeTree(mode,mask,invert,next);
172 return result;
173 }
174 }
175 //If we never recursed, all the pixels in this quadrant have the same "value".
176 result->kind = (last_transparent == SDL_FALSE ? OpaqueShape : TransparentShape);
177 result->data.shape = dimensions;
178 return result;
179 }
180
181 SDL_ShapeTree* SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape,SDL_bool invert) {
182 SDL_Rect dimensions = {0,0,shape->w,shape->h};
183 SDL_ShapeTree* result = NULL;
184 if(SDL_MUSTLOCK(shape))
185 SDL_LockSurface(shape);
186 result = RecursivelyCalculateShapeTree(mode,shape,invert,dimensions);
187 if(SDL_MUSTLOCK(shape))
188 SDL_UnlockSurface(shape);
189 return result;
190 }
191
192 void SDL_TraverseShapeTree(SDL_ShapeTree *tree,void(*function)(SDL_ShapeTree*,void*),void* closure) {
193 if(tree->kind == QuadShape) {
194 SDL_TraverseShapeTree(tree->data.children.upleft,function,closure);
195 SDL_TraverseShapeTree(tree->data.children.upright,function,closure);
196 SDL_TraverseShapeTree(tree->data.children.downleft,function,closure);
197 SDL_TraverseShapeTree(tree->data.children.downright,function,closure);
198 }
199 else
200 function(tree,closure);
201 }
202
203 void SDL_FreeShapeTree(SDL_ShapeTree** shapeTree) {
204 if((*shapeTree)->kind == QuadShape) {
205 SDL_FreeShapeTree(&(*shapeTree)->data.children.upleft);
206 SDL_FreeShapeTree(&(*shapeTree)->data.children.upright);
207 SDL_FreeShapeTree(&(*shapeTree)->data.children.downleft);
208 SDL_FreeShapeTree(&(*shapeTree)->data.children.downright);
209 }
210 free(*shapeTree);
211 *shapeTree = NULL;
106 } 212 }
107 213
108 int SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) { 214 int SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) {
109 int result; 215 int result;
110 if(window == NULL || !SDL_IsShapedWindow(window)) 216 if(window == NULL || !SDL_IsShapedWindow(window))